alloc() never returns Null

Mark alloc()--also dupstr() and re_alloc()--for gcc and clang as
always returning non-Null.  This should silence some of the static
analysis complaints.

Almost all the monster and object naming functions (anything that
returns an mbuf or an obuf) should be marked this way too but I'll
leave that for somebody else to deal with.

I didn't attempt to mark alloc() with the 'malloc' attribute because
macro definitions could end up causing trouble.  Specifying its
deallocator would probably be useful but is at even bigger risk of
macro interference.

I'm not sure whether gcc 3 is really the right test for whether the
returns_nonnull attribute setting is available.
This commit is contained in:
PatR
2022-09-24 04:39:12 -07:00
parent ef093d0b30
commit 4885653014
4 changed files with 17 additions and 12 deletions
+1 -1
View File
@@ -10,7 +10,7 @@
#if 0 #if 0
extern long *alloc(unsigned int); extern long *alloc(unsigned int);
#endif #endif
extern char *fmt_ptr(const void *); extern char *fmt_ptr(const void *) NONNULL;
/* This next pre-processor directive covers almost the entire file, /* This next pre-processor directive covers almost the entire file,
* interrupted only occasionally to pick up specific functions as needed. */ * interrupted only occasionally to pick up specific functions as needed. */
+7 -7
View File
@@ -303,9 +303,9 @@ typedef uchar nhsym;
if nethack is built with MONITOR_HEAP enabled and they aren't; this if nethack is built with MONITOR_HEAP enabled and they aren't; this
declaration has been moved out of the '#else' below to avoid getting declaration has been moved out of the '#else' below to avoid getting
a complaint from -Wmissing-prototypes when building with MONITOR_HEAP */ a complaint from -Wmissing-prototypes when building with MONITOR_HEAP */
extern char *dupstr(const char *); extern char *dupstr(const char *) NONNULL;
/* same, but return strlen(string) */ /* same, but return strlen(string) */
extern char *dupstr_n(const char *string, unsigned int *lenout); extern char *dupstr_n(const char *string, unsigned int *lenout) NONNULL;
/* /*
* MONITOR_HEAP is conditionally used for primitive memory leak debugging. * MONITOR_HEAP is conditionally used for primitive memory leak debugging.
@@ -317,10 +317,10 @@ extern char *dupstr_n(const char *string, unsigned int *lenout);
*/ */
#ifdef MONITOR_HEAP #ifdef MONITOR_HEAP
/* plain alloc() is not declared except in alloc.c */ /* plain alloc() is not declared except in alloc.c */
extern long *nhalloc(unsigned int, const char *, int); extern long *nhalloc(unsigned int, const char *, int) NONNULL;
extern long *nhrealloc(long *, unsigned int, const char *, int); extern long *nhrealloc(long *, unsigned int, const char *, int) NONNULL;
extern void nhfree(genericptr_t, const char *, int); extern void nhfree(genericptr_t, const char *, int);
extern char *nhdupstr(const char *, const char *, int); extern char *nhdupstr(const char *, const char *, int) NONNULL;
/* this predates C99's __func__; that is trickier to use conditionally /* this predates C99's __func__; that is trickier to use conditionally
because it is not implemented as a preprocessor macro; MONITOR_HEAP because it is not implemented as a preprocessor macro; MONITOR_HEAP
wouldn't gain much benefit from it anyway so continue to live without it; wouldn't gain much benefit from it anyway so continue to live without it;
@@ -337,8 +337,8 @@ extern char *nhdupstr(const char *, const char *, int);
#define dupstr(s) nhdupstr(s, __FILE__, (int) __LINE__) #define dupstr(s) nhdupstr(s, __FILE__, (int) __LINE__)
#else /* !MONITOR_HEAP */ #else /* !MONITOR_HEAP */
/* declare alloc.c's alloc(); allocations made with it use ordinary free() */ /* declare alloc.c's alloc(); allocations made with it use ordinary free() */
extern long *alloc(unsigned int); /* alloc.c */ extern long *alloc(unsigned int) NONNULL; /* alloc.c */
extern long *re_alloc(long *, unsigned int); extern long *re_alloc(long *, unsigned int) NONNULL;
#endif /* ?MONITOR_HEAP */ #endif /* ?MONITOR_HEAP */
/* Used for consistency checks of various data files; declare it here so /* Used for consistency checks of various data files; declare it here so
+4
View File
@@ -404,6 +404,7 @@ typedef genericptr genericptr_t; /* (void *) or (char *) */
#if __GNUC__ >= 3 #if __GNUC__ >= 3
#define UNUSED __attribute__((unused)) #define UNUSED __attribute__((unused))
#define NORETURN __attribute__((noreturn)) #define NORETURN __attribute__((noreturn))
#define NONNULL __attribute__((returns_nonnull))
#if !defined(__linux__) || defined(GCC_URWARN) #if !defined(__linux__) || defined(GCC_URWARN)
/* disable gcc's __attribute__((__warn_unused_result__)) since explicitly /* disable gcc's __attribute__((__warn_unused_result__)) since explicitly
discarding the result by casting to (void) is not accepted as a 'use' */ discarding the result by casting to (void) is not accepted as a 'use' */
@@ -422,5 +423,8 @@ typedef genericptr genericptr_t; /* (void *) or (char *) */
#ifndef NORETURN #ifndef NORETURN
#define NORETURN #define NORETURN
#endif #endif
#ifndef NONNULL
#define NONNULL
#endif
#endif /* TRADSTDC_H */ #endif /* TRADSTDC_H */
+5 -4
View File
@@ -19,7 +19,7 @@ extern int FITSint_(LUA_INTEGER, const char *, int);
#define FITSuint(x) FITSuint_(x, __func__, (int) __LINE__) #define FITSuint(x) FITSuint_(x, __func__, (int) __LINE__)
extern unsigned FITSuint_(unsigned long long, const char *, int); extern unsigned FITSuint_(unsigned long long, const char *, int);
char *fmt_ptr(const genericptr); char *fmt_ptr(const genericptr) NONNULL;
#ifdef MONITOR_HEAP #ifdef MONITOR_HEAP
#undef alloc #undef alloc
@@ -32,8 +32,8 @@ static FILE *heaplog = 0;
static boolean tried_heaplog = FALSE; static boolean tried_heaplog = FALSE;
#endif #endif
long *alloc(unsigned int); long *alloc(unsigned int) NONNULL;
long *re_alloc(long *, unsigned int); long *re_alloc(long *, unsigned int) NONNULL;
extern void panic(const char *, ...); extern void panic(const char *, ...);
long * long *
@@ -221,7 +221,8 @@ char *
dupstr_n(const char *string, unsigned int *lenout) dupstr_n(const char *string, unsigned int *lenout)
{ {
size_t len = strlen(string); size_t len = strlen(string);
if(len >= LARGEST_INT)
if (len >= LARGEST_INT)
panic("string too long"); panic("string too long");
*lenout = (unsigned int) len; *lenout = (unsigned int) len;
return strcpy((char *) alloc(len + 1), string); return strcpy((char *) alloc(len + 1), string);