AmendHub

jcs

/

subtext

/

amendments

/

224

util: Add note parameter to xmalloc, xcalloc, and xrealloc

If THINK C supported __func__ this would be much easier, but for now
we have to manually annotate every allocation. This will help find
the source of memory leaks.

jcs made amendment 224 2 months ago
--- util.c Wed Jul 20 15:46:16 2022 +++ util.c Sun Jul 31 18:05:42 2022 @@ -79,10 +79,11 @@ enum { * List of allocations, updated at xmalloc() and xfree(). If an address * passed to xfree() isn't in the list, it indicates a double-free. */ -#define MALLOC_MAP_SIZE 512 +#define MALLOC_MAP_SIZE 1024 struct malloc_map_e { unsigned long addr; unsigned long size; + char note[16]; } malloc_map[MALLOC_MAP_SIZE]; /* @@ -91,6 +92,7 @@ struct malloc_map_e { * a use-after-free. */ #define MALLOC_UAF_SIZE 256 +static const char malloc_uaf_zero[MALLOC_UAF_SIZE] = { 0 }; static char malloc_uaf[MALLOC_UAF_SIZE]; #endif @@ -123,7 +125,7 @@ util_init(void) #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) void * -xmalloc(size_t size) +xmalloc(size_t size, char *note) { void *ptr; #ifdef MALLOC_DEBUG @@ -144,6 +146,7 @@ xmalloc(size_t size) if (malloc_map[n].addr == 0) { malloc_map[n].addr = (unsigned long)ptr; malloc_map[n].size = size; + strlcpy(malloc_map[n].note, note, sizeof(malloc_map[n].note)); break; } } @@ -167,6 +170,7 @@ xfree(void *ptrptr) if (malloc_map[n].addr == *addr) { malloc_map[n].addr = 0; malloc_map[n].size = 0; + malloc_map[n].note[0] = '\0'; break; } } @@ -185,34 +189,31 @@ xfree(void *ptrptr) void xfree_verify(void) { - size_t n; - - for (n = 0; n < sizeof(malloc_uaf); n++) - if (malloc_uaf[0] != '\0') - panic("xfree_verify: use-after-free detected"); + if (memcmp(malloc_uaf, malloc_uaf_zero, sizeof(malloc_uaf)) != 0) + panic("xfree_verify: use-after-free detected"); } #endif void * -xmalloczero(size_t size) +xmalloczero(size_t size, char *note) { void *ptr; - ptr = xmalloc(size); + ptr = xmalloc(size, note); memset(ptr, 0, size); return ptr; } void * -xcalloc(size_t nmemb, size_t size) +xcalloc(size_t nmemb, size_t size, char *note) { void *ptr; if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && nmemb > 0 && SIZE_MAX / nmemb < size) panic("xcalloc(%lu, %lu) overflow", nmemb, size); - ptr = xmalloczero(nmemb * size); + ptr = xmalloczero(nmemb * size, note); if (ptr == NULL) panic("xcalloc(%lu, %lu) failed", nmemb, size); @@ -222,25 +223,29 @@ xcalloc(size_t nmemb, size_t size) void * xrealloc(void *src, size_t size) { - void *ptr; + void *ptr, *tsrc; unsigned long n; - - ptr = xmalloc(size); - if (src != NULL) { - memcpy(ptr, src, size); + char note[16] = { 0 }; + #ifdef MALLOC_DEBUG + if (src != NULL) { for (n = 0; n <= MALLOC_MAP_SIZE; n++) { if (n == MALLOC_MAP_SIZE) - panic("xrealloc(0x%lx, %lu): can't find in alloc map, " - "double-free or bogus pointer passed", src, size); + panic("xrealloc(%lu): can't find %lu in alloc map, likely " + "double free()", (unsigned long)src); if (malloc_map[n].addr == (unsigned long)src) { - malloc_map[n].addr = 0; - malloc_map[n].size = 0; + strlcpy(note, malloc_map[n].note, sizeof(note)); break; } } + } #endif - DisposePtr(src); + + ptr = xmalloc(size, note); + if (src != NULL) { + memcpy(ptr, src, size); + tsrc = src; + xfree(&tsrc); } return ptr; @@ -256,14 +261,14 @@ xreallocarray(void *optr, size_t nmemb, size_t size) } char * -xstrdup(const char *str) +xstrdup(const char *str, char *note) { char *cp; size_t len; len = strlen(str); - cp = xmalloc(len + 1); + cp = xmalloc(len + 1, note); strlcpy(cp, str, len + 1); return cp; @@ -281,7 +286,7 @@ getline(char *str, size_t len, char **ret) for (i = 0; i < len; i++) { if (str[i] == '\r' || i == len - 1) { if (*ret == NULL) - *ret = xmalloc(i + 1); + *ret = xmalloc(i + 1, "getline"); memcpy(*ret, str, i + 1); (*ret)[i] = '\0'; return i + 1; @@ -387,7 +392,7 @@ void vwarn(short alert_func, const char *format, va_list ap) { Rect bounds; - short quit = 0, height, width, hit; + short height, width, hit; WindowPtr win, dialog; GetPort(&win); @@ -446,9 +451,6 @@ vwarn(short alert_func, const char *format, va_list ap HUnlock(alert_ditl_h); SetPort(win); - - if (quit) - ExitToShell(); } void @@ -662,7 +664,7 @@ xGetStringAsChar(short id) h = xGetString(id); HLock(h); l = (*h)[0]; - out = xmalloc(l + 1); + out = xmalloc(l + 1, "xGetStringAsChar"); memcpy((void *)out, (void *)(*h + 1), l); out[l] = '\0'; ReleaseResource(h); @@ -717,7 +719,7 @@ getpath(short vRefNum, Str255 fileName, Str255 *ret, b return 0; } - name = xmalloc(FILENAME_MAX); + name = xmalloc(FILENAME_MAX, "getpath"); wdir.ioVRefNum = wdir.ioWDVRefNum = vRefNum; wdir.ioWDIndex = 0; @@ -751,8 +753,8 @@ getpath(short vRefNum, Str255 fileName, Str255 *ret, b wcinfo.ioDrParID = wdir.ioWDDirID; wcinfo.ioDrDirID = wdir.ioWDDirID; - tmp = xmalloc(FILENAME_MAX); - tmpret = xmalloc(FILENAME_MAX); + tmp = xmalloc(FILENAME_MAX, "getpath"); + tmpret = xmalloc(FILENAME_MAX, "getpath"); /* go backwards, prepending each folder's parent */ while (wcinfo.ioDrParID != 1) { @@ -805,7 +807,7 @@ stat(char *path, struct stat *sb) char *ppath; short ret; - ppath = xstrdup(path); + ppath = xstrdup(path, "stat"); CtoPstr(ppath); ret = FStat((unsigned char *)ppath, sb); xfree(&ppath); @@ -948,7 +950,7 @@ copy_file_contents(short source_ref, short dest_ref) if (error) return error; - buf = xmalloc(1024); + buf = xmalloc(1024, "copy_file_contents"); while (source_size > 0) { count = 1024; --- util.h Wed Jul 20 15:08:46 2022 +++ util.h Sat Jul 30 22:35:23 2022 @@ -89,14 +89,14 @@ struct stat { void util_init(void); -void * xmalloc(size_t); +void * xmalloc(size_t, char *note); void xfree(void *ptrptr); void xfree_verify(void); -void * xmalloczero(size_t); -void * xcalloc(size_t, size_t); +void * xmalloczero(size_t, char *note); +void * xcalloc(size_t, size_t, char *note); void * xrealloc(void *src, size_t size); void * xreallocarray(void *, size_t, size_t); -char * xstrdup(const char *); +char * xstrdup(const char *, char *note); short getline(char *str, size_t len, char **ret); size_t strlcpy(char *dst, const char *src, size_t dsize);