fix static analyzer vs alloc.c

gcc-13.1 static analyzer complains that alloc() returns long *
without guaranteeing to allocate an integral number of longs.  Fix
by rounding the requested amount up to the next long when dividing
the amount by 'sizeof (long)' yields a remainder.  Surprisingly--to
me, at least--the analyzer recognizes that this extra argument
manipulation will always produce a viable amount no matter what
alloc()'s caller passes in.

Also, the declarations for alloc() and re_alloc() in alloc.c didn't
match the ones in global.h for the MONITOR_HEAP config.  I guess
nobody has tested that since NONNULL got introduced.

A year ago the two FITSxxx routines were moved from hacklib.c to
alloc.c so that they could easily be linked into various programs
instead of being replicated in each, but the declarations for them
weren't moved from hacklib.c section in extern.h to alloc.c one.
This commit is contained in:
PatR
2023-06-21 03:31:41 -07:00
parent e5055e5f60
commit 1209b15bcf
2 changed files with 44 additions and 8 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 alloc.c $NHDT-Date: 1596498147 2020/08/03 23:42:27 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.18 $ */
/* NetHack 3.7 alloc.c $NHDT-Date: 1687343500 2023/06/21 10:31:40 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.31 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -32,8 +32,34 @@ static FILE *heaplog = 0;
static boolean tried_heaplog = FALSE;
#endif
/*
* For historical reasons, nethack's alloc() returns 'long *' rather
* than 'void *' or 'char *'.
*
* Some static analysis complains if it can't deduce that the number
* of bytes being allocated is a multiple of 'sizeof (long)'. It
* recognizes that the following manipulation overcomes that via
* rounding the requested length up to the next long. NetHack doesn't
* make a lot of tiny allocations, so this shouldn't waste much memory
* regardless of whether malloc() does something similar.
*/
#define ForceAlignedLength(LTH) \
do { \
if ((LTH) % sizeof (long) != 0) \
(LTH) += sizeof (long) - (LTH) % sizeof (long); \
} while (0)
#ifndef MONITOR_HEAP
long *alloc(unsigned int) NONNULL;
long *re_alloc(long *, unsigned int) NONNULL;
#else
/* for #if MONITOR_HEAP, alloc() might return Null but only nhalloc()
should be calling it; nhalloc() never returns Null */
long *alloc(unsigned int);
long *re_alloc(long *, unsigned int);
long *nhalloc(unsigned int, const char *, int) NONNULL;
long *nhrealloc(long *, unsigned int, const char *, int) NONNULL;
#endif
ATTRNORETURN extern void panic(const char *, ...) PRINTF_F(1, 2) NORETURN;
long *
@@ -41,10 +67,13 @@ alloc(unsigned int lth)
{
register genericptr_t ptr;
ForceAlignedLength(lth);
ptr = malloc(lth);
#ifndef MONITOR_HEAP
if (!ptr)
panic("Memory allocation failure; cannot get %u bytes", lth);
#else
/* for #if MONITOR_HEAP, failure is handled in nhalloc() */
#endif
return (long *) ptr;
}
@@ -53,11 +82,16 @@ alloc(unsigned int lth)
long *
re_alloc(long *oldptr, unsigned int newlth)
{
long *newptr = (long *) realloc((genericptr_t) oldptr, (size_t) newlth);
long *newptr;
ForceAlignedLength(newlth);
newptr = (long *) realloc((genericptr_t) oldptr, (size_t) newlth);
#ifndef MONITOR_HEAP
/* "extend to": assume it won't ever fail if asked to shrink */
if (newlth && !newptr)
panic("Memory allocation failure; cannot extend to %u bytes", newlth);
#else
/* for #if MONITOR_HEAP, failure is handled in nhrealloc() */
#endif
return newptr;
}
@@ -202,7 +236,7 @@ dupstr(const char *string)
return strcpy((char *) alloc(len + 1), string);
}
/* similar for reasonable size strings, but return the length of the input as well */
/* similar for reasonable size strings, but return length of input as well */
char *
dupstr_n(const char *string, unsigned int *lenout)
{