From: PatR Date: Tue, 31 May 2022 06:19:35 +0000 (-0700) Subject: implement realloc() for MONITOR_HEAP or vice versa X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=687e7c12f703c2269fd0d8d656eacae6b98670e1;p=nethack implement realloc() for MONITOR_HEAP or vice versa Add new routine 're_alloc()' that functions as MONITOR_HEAP-aware libc realloc(). 'nhrealloc()' is the version that passes source file and line info if built with MONITOR_HEAP enabled. The heaplog data might now contain '<' (freed by realloc), '>' (replacement allocation by realloc), and '*' (resized by realloc) entries in addition to the previous '+' (allocated) and '-' (freed) entries. heaputil has already been updated in the NHinternal repository. Move FITSint_() and FITSuint_() from hacklib.c to alloc.c so that they can be accessed by miscellaneous utility programs. Remove three or four copies of FITSint_() that were duplicated in utility programs like dlb and tile2bmp due to those not having access to src/hacklib.o. They do have access to src/alloc.o (and util/panic.o). --- diff --git a/include/global.h b/include/global.h index 41659e4dc..358f66a12 100644 --- a/include/global.h +++ b/include/global.h @@ -301,6 +301,7 @@ extern char *dupstr_n(const char *string, unsigned int *lenout); #ifdef MONITOR_HEAP /* plain alloc() is not declared except in alloc.c */ extern long *nhalloc(unsigned int, const char *, int); +extern long *nhrealloc(long *, unsigned int, const char *, int); extern void nhfree(genericptr_t, const char *, int); extern char *nhdupstr(const char *, const char *, int); /* this predates C99's __func__; that is trickier to use conditionally @@ -314,11 +315,13 @@ extern char *nhdupstr(const char *, const char *, int); #define __LINE__ 0 #endif #define alloc(a) nhalloc(a, __FILE__, (int) __LINE__) +#define re_alloc(a,n) nhrealloc(a, n, __FILE__, (int) __LINE__) #define free(a) nhfree(a, __FILE__, (int) __LINE__) #define dupstr(s) nhdupstr(s, __FILE__, (int) __LINE__) #else /* !MONITOR_HEAP */ /* declare alloc.c's alloc(); allocations made with it use ordinary free() */ extern long *alloc(unsigned int); /* alloc.c */ +extern long *re_alloc(long *, unsigned int); #endif /* ?MONITOR_HEAP */ /* Used for consistency checks of various data files; declare it here so diff --git a/src/alloc.c b/src/alloc.c index c4642d9ed..f0fb41a71 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -8,16 +8,22 @@ /* since this file is also used in auxiliary programs, don't include all the function declarations for all of nethack */ #define EXTERN_H /* comment line for pre-compiled headers */ -/* but we need this one */ -#define FITSuint(x) FITSuint_(x, __func__, __LINE__) -extern unsigned FITSuint_(unsigned long long, const char *, int); #include "config.h" +#ifndef LUA_INTEGER +#include "nhlua.h" +#endif + +#define FITSint(x) FITSint_(x, __func__, (int) __LINE__) +extern int FITSint_(LUA_INTEGER, const char *, int); +#define FITSuint(x) FITSuint_(x, __func__, (int) __LINE__) +extern unsigned FITSuint_(unsigned long long, const char *, int); char *fmt_ptr(const genericptr); #ifdef MONITOR_HEAP #undef alloc +#undef re_alloc #undef free extern void free(genericptr_t); static void heapmon_init(void); @@ -27,6 +33,7 @@ static boolean tried_heaplog = FALSE; #endif long *alloc(unsigned int); +long *re_alloc(long *, unsigned int); extern void panic(const char *, ...); long * @@ -55,6 +62,24 @@ alloc(unsigned int lth) #endif } +/* realloc() call that might get substituted by nhrealloc(p,l,file,line) */ +long * +re_alloc(long *oldptr, unsigned int newlth) +{ + /* + * if LINT support ever gets resurrected, + * we probably need some hackery here + */ + + long *newptr = (long *) realloc((genericptr_t) oldptr, (size_t) newlth); +#ifndef MONITOR_HEAP + /* "extend": assume if won't ever fail if asked to shrink */ + if (newlth && !newptr) + panic("Memory allocation failure; cannot extend to %u bytes", newlth); +#endif + return newptr; +} + #ifdef HAS_PTR_FMT #define PTR_FMT "%p" #define PTR_TYP genericptr_t @@ -122,6 +147,39 @@ nhalloc(unsigned int lth, const char *file, int line) return ptr; } +/* re_alloc() with heap logging; we lack access to the old alloc size */ +long * +nhrealloc( + long *oldptr, + unsigned int newlth, + const char *file, + int line) +{ + long *newptr = re_alloc(oldptr, newlth); + + if (!tried_heaplog) + heapmon_init(); + if (heaplog) { + char op = '*'; /* assume realloc() will change size of previous + * allocation rather than make a new one */ + + if (newptr != oldptr) { + /* realloc() freed oldptr */ + (void) fprintf(heaplog, "%c%5s %s %4d %s\n", '<', "", + fmt_ptr((genericptr_t) oldptr), line, file); + op = '>'; /* new allocation rather than size-change of old one */ + } + (void) fprintf(heaplog, "%c%5u %s %4d %s\n", op, newlth, + fmt_ptr((genericptr_t) newptr), line, file); + } + /* potential panic in re_alloc() was deferred til here */ + /* "extend to": assume if won't ever fail if asked to shrink */ + if (newlth && !newptr) + panic("Cannot extend to %u bytes, line %d of %s", newlth, line, file); + + return newptr; +} + void nhfree(genericptr_t ptr, const char *file, int line) { @@ -166,4 +224,25 @@ dupstr_n(const char *string, unsigned int *lenout) return strcpy((char *) alloc(len + 1), string); } +/* cast to int or panic on overflow; use via macro */ +int +FITSint_(LUA_INTEGER i, const char *file, int line) +{ + int iret = (int) i; + + if (iret != i) + panic("Overflow at %s:%d", file, line); + return iret; +} + +unsigned +FITSuint_(unsigned long long ull, const char *file, int line) +{ + unsigned uret = (unsigned) ull; + + if (uret != ull) + panic("Overflow at %s:%d", file, line); + return uret; +} + /*alloc.c*/ diff --git a/src/hacklib.c b/src/hacklib.c index 532046c48..98ca4e90a 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -1361,23 +1361,6 @@ nh_snprintf( RESTORE_WARNING_FORMAT_NONLITERAL -/* cast to int or panic on overflow; use via macro */ -int -FITSint_(lua_Integer i, const char *file, int line){ - int ret = (int)i; - if (ret != i) - panic("Overflow at %s:%d", file, line); - return (int)i; -} - -unsigned -FITSuint_(unsigned long long i, const char *file, int line){ - unsigned ret = (unsigned)i; - if (ret != i) - panic("Overflow at %s:%d", file, line); - return (unsigned)i; -} - #ifdef ENHANCED_SYMBOLS /* Unicode routines */ diff --git a/src/nhlua.c b/src/nhlua.c index 75ab9422d..5fc39a7e1 100644 --- a/src/nhlua.c +++ b/src/nhlua.c @@ -2255,11 +2255,8 @@ nhl_alloc(void *ud, void *ptr, size_t osize, size_t nsize) free(ptr); return NULL; } - /* - * FIXME: - * Use of realloc() confuses MONITOR_HEAP. - */ - return realloc(ptr, nsize); + + return re_alloc(ptr, nsize); } static int diff --git a/util/dlb_main.c b/util/dlb_main.c index 5c886c25d..e434b3a33 100644 --- a/util/dlb_main.c +++ b/util/dlb_main.c @@ -15,6 +15,7 @@ #endif static void xexit(int) NORETURN; +extern void panic(const char *, ...) NORETURN; char *eos(char *); /* also used by dlb.c */ FILE *fopen_datafile(const char *, const char *); unsigned FITSuint_(unsigned long long, const char *, int); @@ -545,25 +546,15 @@ xexit(int retcd) /*NOTREACHED*/ } - /* In hacklib.c, but we don't have that and it calls panic() */ +/* from hacklib.c */ unsigned -FITSuint_(unsigned long long i, const char *file, int line){ - unsigned ret = (unsigned)i; - if (ret != i) { - printf("Overflow at %s:%d\n", file, line); - xexit(EXIT_FAILURE); - } - return (unsigned)i; -} - - /* ditto */ -unsigned -Strlen_(const char *str, const char *file, int line){ +Strlen_(const char *str, const char *file, int line) +{ size_t len = strnlen(str, LARGEST_INT); if (len == LARGEST_INT) { - printf("%s:%d string too long", file, line); - xexit(EXIT_FAILURE); + panic("%s:%d string too long", file, line); + /*NOTREACHED*/ } return (unsigned) len; } diff --git a/util/makedefs.c b/util/makedefs.c index 6f64341a8..d0d195f34 100644 --- a/util/makedefs.c +++ b/util/makedefs.c @@ -2351,14 +2351,4 @@ struct attribs attrmax, attrmin; #endif #endif /* STRICT_REF_DEF */ -/* In hacklib.c, but we don't have that and it calls panic() */ -unsigned -FITSuint_(unsigned long long i, const char *file, int line){ -unsigned ret = (unsigned)i; -if (ret != i) { - Fprintf(stdout, "Overflow at %s:%d\n", file, line); - makedefs_exit(EXIT_FAILURE); -} -return (unsigned)i; -} /*makedefs.c*/ diff --git a/win/X11/tile2x11.c b/win/X11/tile2x11.c index 97059dd5e..53e7e57d2 100644 --- a/win/X11/tile2x11.c +++ b/win/X11/tile2x11.c @@ -241,14 +241,5 @@ main(int argc, char *argv[]) return 0; } -/* we need a local copy of this for alloc.o and because we don't have panic() */ -unsigned -FITSuint_(unsigned long long i, const char *file, int line){ - unsigned ret = (unsigned)i; - if (ret != i) { - Fprintf(stderr, "Overflow at %s:%d", file, line); - exit(1); - } - return (unsigned)i; -} +/*tile2X11.c*/ diff --git a/win/share/tile2bmp.c b/win/share/tile2bmp.c index d45bbbd83..fc1942be1 100644 --- a/win/share/tile2bmp.c +++ b/win/share/tile2bmp.c @@ -379,14 +379,5 @@ build_bmptile(pixel(*pixels)[TILE_X]) } } -/* we need a local copy of this for alloc.o and because we don't have panic() */ -unsigned -FITSuint_(unsigned long long i, const char *file, int line){ - unsigned ret = (unsigned)i; - if (ret != i) { - Fprintf(stderr, "Overflow at %s:%d", file, line); - exit(EXIT_FAILURE); - } - return (unsigned)i; -} +/*tile2bmp.c*/