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 over 2 years 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);