Re: [PATCH 4/4] git-compat-util.h: dietlibc-friendly x{malloc,realloc,calloc}
From: Eric Wong <hidden>
Date: 2016-06-15 22:42:15
Subsystem:
the rest · Maintainer:
Linus Torvalds
Possibly related (same subject, not in this thread)
- 2016-06-15 · [PATCH 4/4] git-compat-util.h: dietlibc-friendly x{malloc,realloc,calloc} · Eric Wong <hidden>
Junio C Hamano [off-list ref] wrote:
Eric Wong [off-list ref] writes:quoted
dietlibc versions of these allocators returns NULL if a size of zero is specified. Obviously, this is a problem with the x* wrappers since we check for them returning NULL. Down the line, it'd be better to hunt down and eliminate all calls to these functions when they are called with a zero argument. I've already added some checks for these cases that were exposed by tests.I agree that it is a bug to rely on *alloc(0) not returning NULL, but this patch is too risky. It would be a good thing to have debugging variant of x* wrappers that barf on a 0-byte allocation request to find the offending callers, instead of returning NULL, maybe like the attached patch. Since eradicating *alloc(0) calls is the right way to go, but it takes time. Touching x* wrappers for general public should not be done before it is done. It breaks things for everybody, while the current code is broken only for diet people and developers that use the debugging variant of x* wrappers.
I'll be using the following patch to collect results for the next few days without interrupting my work on other projects. I'll post patches to remove *alloc(0) calls when I find them.
diff --git a/git-compat-util.h b/git-compat-util.h
index 0c98c99..43be289 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h@@ -60,9 +60,41 @@ extern int gitsetenv(const char *, const extern char *gitstrcasestr(const char *haystack, const char *needle); #endif +static void fork_for_core (const char * caller) +{ + pid_t child = fork(); + if (child == 0) { + int i; + char out[4096]; + char * progname = "unknown"; + FILE * dbg = fopen("/var/tmp/git_alloc_dbg.log","a"); + + for(i = 0; environ[i]; i++) { + if (strstr(environ[i],"_=") == environ[i]) + progname = environ[i]; + } + + snprintf(out, 4096, "%s:%s: pid %d dumping core for pid %d\n", + progname, caller, getpid(), getppid()); + + fputs(out, stderr); + fputs(out, dbg); + fflush(NULL); + + abort(); + } +} + static inline void *xmalloc(size_t size) { - void *ret = malloc(size); + void *ret; + + if (!size) { + fork_for_core(__func__); + return NULL; + } + + ret = malloc(size); if (!ret) die("Out of memory, malloc failed"); return ret;
@@ -70,7 +102,15 @@ static inline void *xmalloc(size_t size) static inline void *xrealloc(void *ptr, size_t size) { - void *ret = realloc(ptr, size); + void *ret; + + if (!size) { + fork_for_core(__func__); + free(ptr); + return NULL; + } + + ret = realloc(ptr, size); if (!ret) die("Out of memory, realloc failed"); return ret;
@@ -78,7 +118,14 @@ static inline void *xrealloc(void *ptr, static inline void *xcalloc(size_t nmemb, size_t size) { - void *ret = calloc(nmemb, size); + void *ret; + + if (!nmemb || !size) { + fork_for_core(__func__); + return NULL; + } + + ret = calloc(nmemb, size); if (!ret) die("Out of memory, calloc failed"); return ret;
--
Eric Wong