{"thread":{"id":"2924","subject":"[PATCH 0/4] dietlibc compatibility","startedAt":"2005-12-24T12:10:07Z","lastAt":"2005-12-30T23:00:35Z","messageCount":24,"participants":["Eric Wong","Junio C Hamano","Johannes Schindelin","H. Peter Anvin","Linus Torvalds"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"14006","messageId":"20051224121007.GA19136@mail.yhbt.net","threadId":"2924","inReplyTo":null,"subject":"[PATCH 0/4] dietlibc compatibility","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2005-12-24T12:10:07Z","receivedAt":"2005-12-24T12:10:07Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"I've started statically-linking git binaries against dietlibc to avoid\nhaving to recompile it for every machine/distro and chroot (lots!) I\nwould use it in.\n\nFor building git (on a Debian unstable system with dietlibc-dev),\nI used the following make vars:\n\n\tCC=diet -v gcc\n\tNO_STRCASESTR=YesPlease\n\tNO_SETENV=YesPlease\n\nThe dietlibc setenv() doesn't seem very nice to **envp in git.c,\nresulting in $PATH being clobbered when it runs execve().  This\ncaused tests to fail.  Fortunately, gitsetenv() saved the day.\n\nThe following patches fix other issues I had with dietlibc.\n\n-- \nEric Wong\n"},{"id":"14007","messageId":"20051224121117.GB19136@mail.yhbt.net","threadId":"2924","inReplyTo":"20051224121007.GA19136@mail.yhbt.net","subject":"[PATCH 1/4] git.c: extra #include for dietlibc (and possibly other C libraries)","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2005-12-24T12:11:17Z","receivedAt":"2005-12-24T12:11:17Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"struct winsize is defined in <termios.h>, and that's not pulled\nin by other #includes in that file\n\nSigned-off-by: Eric Wong <normalperson@yhbt.net>\n\n---\n\n git.c |    1 +\n 1 files changed, 1 insertions(+), 0 deletions(-)\n\nae5641fcbc58509572d080c33a20c829b82ae9b0\ndiff --git a/git.c b/git.c\nindex e795ddb..434a3d9 100644\n--- a/git.c\n+++ b/git.c\n@@ -9,6 +9,7 @@\n #include <limits.h>\n #include <stdarg.h>\n #include <sys/ioctl.h>\n+#include <termios.h>\n #include \"git-compat-util.h\"\n \n #ifndef PATH_MAX\n-- \n1.0.GIT\n"},{"id":"14008","messageId":"20051224121243.GA3963@mail.yhbt.net","threadId":"2924","inReplyTo":"20051224121007.GA19136@mail.yhbt.net","subject":"[PATCH 2/4] short circuit out of a few places where we would allocate zero bytes","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2005-12-24T12:12:43Z","receivedAt":"2005-12-24T12:12:43Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"dietlibc versions of malloc, calloc and realloc all return NULL if\nthey're told to allocate 0 bytes, causes the x* wrappers to die().\n\nThere are several more places where these calls could end up asking\nfor 0 bytes, too...\n\nMaybe simply not die()-ing in the x* wrappers if 0/NULL is returned\nwhen the requested size is zero is a safer and easier way to go.\n\nSigned-off-by: Eric Wong <normalperson@yhbt.net>\n\n---\n\n commit.c          |    3 +++\n diffcore-rename.c |    2 +-\n 2 files changed, 4 insertions(+), 1 deletions(-)\n\nee9d90c652be126345dec2ac204284e80e685160\ndiff --git a/commit.c b/commit.c\nindex e867b86..edd4ded 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -560,6 +560,9 @@ void sort_in_topological_order(struct co\n \t\tnext = next->next;\n \t\tcount++;\n \t}\n+\t\n+\tif (!count)\n+\t\treturn;\n \t/* allocate an array to help sort the list */\n \tnodes = xcalloc(count, sizeof(*nodes));\n \t/* link the list to the array */\ndiff --git a/diffcore-rename.c b/diffcore-rename.c\nindex dba965c..39d9126 100644\n--- a/diffcore-rename.c\n+++ b/diffcore-rename.c\n@@ -282,7 +282,7 @@ void diffcore_rename(struct diff_options\n \t\telse if (detect_rename == DIFF_DETECT_COPY)\n \t\t\tregister_rename_src(p->one, 1);\n \t}\n-\tif (rename_dst_nr == 0 ||\n+\tif (rename_dst_nr == 0 || rename_src_nr == 0 ||\n \t    (0 < rename_limit && rename_limit < rename_dst_nr))\n \t\tgoto cleanup; /* nothing to do */\n \n-- \n1.0.GIT\n"},{"id":"14009","messageId":"20051224121339.GB3963@mail.yhbt.net","threadId":"2924","inReplyTo":"20051224121007.GA19136@mail.yhbt.net","subject":"[PATCH 3/4] add xmktime() function that always accounts for the TZ env","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2005-12-24T12:13:39Z","receivedAt":"2005-12-24T12:13:39Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"This function was added because mktime in dietlibc doesn't seem to\naccount for the TZ env.  Also, xmktime() now shares the same\nalways-summer bug TZ parsing elsewhere, so at least we can\nbe wrong about summer consistently.\n\nSigned-off-by: Eric Wong <normalperson@yhbt.net>\n\n---\n\n cache.h           |    2 ++\n convert-objects.c |    4 ++--\n date.c            |   30 ++++++++++++++++++++++++++----\n 3 files changed, 30 insertions(+), 6 deletions(-)\n\n3b0763ae6fce6c69021e1216660f4c0ee301512b\ndiff --git a/cache.h b/cache.h\nindex cb87bec..c5ff4b7 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -5,6 +5,7 @@\n \n #include SHA1_HEADER\n #include <zlib.h>\n+#include <time.h>\n \n #if ZLIB_VERNUM < 0x1200\n #define deflateBound(c,s)  ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11)\n@@ -236,6 +237,7 @@ extern void *read_object_with_reference(\n \n const char *show_date(unsigned long time, int timezone);\n int parse_date(const char *date, char *buf, int bufsize);\n+time_t xmktime(struct tm *tm);\n void datestamp(char *buf, int bufsize);\n unsigned long approxidate(const char *);\n \ndiff --git a/convert-objects.c b/convert-objects.c\nindex b49bce2..0fe1229 100644\n--- a/convert-objects.c\n+++ b/convert-objects.c\n@@ -178,7 +178,7 @@ static unsigned long parse_oldstyle_date\n \t\tconst char *next = strptime(buf, *fmt, &tm);\n \t\tif (next) {\n \t\t\tif (!*next)\n-\t\t\t\treturn mktime(&tm);\n+\t\t\t\treturn xmktime(&tm);\n \t\t\tbuf = next;\n \t\t} else {\n \t\t\tconst char **p = timezones;\n@@ -195,7 +195,7 @@ static unsigned long parse_oldstyle_date\n \t\tfmt++;\n \t} while (*buf && *fmt);\n \tprintf(\"left: %s\\n\", buf);\n-\treturn mktime(&tm);\t\t\t\t\n+\treturn xmktime(&tm);\t\t\t\t\n }\n \n static int convert_date_line(char *dst, void **buf, unsigned long *sp)\ndiff --git a/date.c b/date.c\nindex 3e11500..5596476 100644\n--- a/date.c\n+++ b/date.c\n@@ -141,6 +141,28 @@ static int match_string(const char *date\n \treturn i;\n }\n \n+time_t xmktime(struct tm *tm)\n+{\n+\ttime_t ret = my_mktime(tm);\n+\tchar * tz = getenv(\"TZ\");\n+\n+\tif (tz) {\n+\t\tint i;\n+\t\tfor (i = 0; i < NR_TZ; i++) {\n+\t\t\tint match = match_string(tz, timezone_names[i].name);\n+\t\t\tif (match >= 3) {\n+\t\t\t\tint off = timezone_names[i].offset;\n+\n+\t\t\t\t/* This is bogus, but we like summer */\n+\t\t\t\toff += timezone_names[i].dst;\n+\t\t\t\t\n+\t\t\t\tret += 60*off;\n+\t\t\t}\n+\t\t}\n+\t}\n+\treturn ret;\n+}\n+\n static int skip_alpha(const char *date)\n {\n \tint i = 0;\n@@ -436,10 +458,10 @@ int parse_date(const char *date, char *r\n \t\tdate += match;\n \t}\n \n-\t/* mktime uses local timezone */\n+\t/* (x)mktime uses local timezone */\n \tthen = my_mktime(&tm); \n \tif (offset == -1)\n-\t\toffset = (then - mktime(&tm)) / 60;\n+\t\toffset = (then - xmktime(&tm)) / 60;\n \n \tif (then == -1)\n \t\treturn -1;\n@@ -464,7 +486,7 @@ void datestamp(char *buf, int bufsize)\n \n static void update_tm(struct tm *tm, unsigned long sec)\n {\n-\ttime_t n = mktime(tm) - sec;\n+\ttime_t n = xmktime(tm) - sec;\n \tlocaltime_r(&n, tm);\n }\n \n@@ -642,5 +664,5 @@ unsigned long approxidate(const char *da\n \t\ttm.tm_mday = number;\n \tif (tm.tm_mon > now.tm_mon)\n \t\ttm.tm_year--;\n-\treturn mktime(&tm);\n+\treturn xmktime(&tm);\n }\n-- \n1.0.GIT\n"},{"id":"14010","messageId":"20051224121454.GC3963@mail.yhbt.net","threadId":"2924","inReplyTo":"20051224121007.GA19136@mail.yhbt.net","subject":"[PATCH 4/4] git-compat-util.h: dietlibc-friendly x{malloc,realloc,calloc}","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2005-12-24T12:14:54Z","receivedAt":"2005-12-24T12:14:54Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"dietlibc versions of these allocators returns NULL if a size of zero is\nspecified.  Obviously, this is a problem with the x* wrappers since\nwe check for them returning NULL.\n\nDown the line, it'd be better to hunt down and eliminate all calls to\nthese functions when they are called with a zero argument.  I've already\nadded some checks for these cases that were exposed by tests.\n\nSigned-off-by: Eric Wong <normalperson@yhbt.net>\n\n---\n\n git-compat-util.h |   23 ++++++++++++++++++++---\n 1 files changed, 20 insertions(+), 3 deletions(-)\n\n113dca27f9f95a76a0f98929720f5f567c7586b2\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 0c98c99..bd2f150 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -62,7 +62,12 @@ extern char *gitstrcasestr(const char *h\n \n static inline void *xmalloc(size_t size)\n {\n-\tvoid *ret = malloc(size);\n+\tvoid *ret;\n+\t\n+\tif (!size)\n+\t\treturn NULL;\n+\t\n+\tret = malloc(size);\n \tif (!ret)\n \t\tdie(\"Out of memory, malloc failed\");\n \treturn ret;\n@@ -70,7 +75,14 @@ static inline void *xmalloc(size_t size)\n \n static inline void *xrealloc(void *ptr, size_t size)\n {\n-\tvoid *ret = realloc(ptr, size);\n+\tvoid *ret;\n+\t\n+\tif (!size) {\n+\t\tfree(ptr);\n+\t\treturn NULL;\n+\t}\n+\t\n+\tret = realloc(ptr, size);\n \tif (!ret)\n \t\tdie(\"Out of memory, realloc failed\");\n \treturn ret;\n@@ -78,7 +90,12 @@ static inline void *xrealloc(void *ptr, \n \n static inline void *xcalloc(size_t nmemb, size_t size)\n {\n-\tvoid *ret = calloc(nmemb, size);\n+\tvoid *ret;\n+\t\n+\tif (!nmemb || !size)\n+\t\treturn NULL;\n+\t\n+\tret = calloc(nmemb, size);\n \tif (!ret)\n \t\tdie(\"Out of memory, calloc failed\");\n \treturn ret;\n-- \n1.0.GIT\n"},{"id":"14033","messageId":"Pine.LNX.4.63.0512241342100.5891@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"2924","inReplyTo":"20051224121243.GA3963@mail.yhbt.net","subject":"Re: [PATCH 2/4] short circuit out of a few places where we would allocate zero bytes","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2005-12-24T12:44:13Z","receivedAt":"2005-12-24T12:44:13Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 24 Dec 2005, Eric Wong wrote:\n\n> dietlibc versions of malloc, calloc and realloc all return NULL if\n> they're told to allocate 0 bytes, causes the x* wrappers to die().\n> \n> There are several more places where these calls could end up asking\n> for 0 bytes, too...\n> \n> Maybe simply not die()-ing in the x* wrappers if 0/NULL is returned\n> when the requested size is zero is a safer and easier way to go.\n\nI would prefer that, too. But the cleanest way would be to prevent calls \nto *alloc if the size is 0...\n\nCiao,\nDscho\n"},{"id":"14036","messageId":"Pine.LNX.4.63.0512241344200.5891@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"2924","inReplyTo":"20051224121339.GB3963@mail.yhbt.net","subject":"Re: [PATCH 3/4] add xmktime() function that always accounts for the TZ env","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2005-12-24T12:45:50Z","receivedAt":"2005-12-24T12:45:50Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 24 Dec 2005, Eric Wong wrote:\n\n> This function was added because mktime in dietlibc doesn't seem to\n> account for the TZ env.  Also, xmktime() now shares the same\n> always-summer bug TZ parsing elsewhere, so at least we can\n> be wrong about summer consistently.\n\nHow about making this a compat function, which is used when the Makefile \nvariable MKTIME_IGNORES_TZ is set?\n\nCiao,\nDscho\n"},{"id":"14018","messageId":"7v3bkis631.fsf@assigned-by-dhcp.cox.net","threadId":"2924","inReplyTo":"20051224121454.GC3963@mail.yhbt.net","subject":"Re: [PATCH 4/4] git-compat-util.h: dietlibc-friendly x{malloc,realloc,calloc}","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-24T18:28:02Z","receivedAt":"2005-12-24T18:28:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Wong <normalperson@yhbt.net> writes:\n\n> dietlibc versions of these allocators returns NULL if a size of zero is\n> specified.  Obviously, this is a problem with the x* wrappers since\n> we check for them returning NULL.\n>\n> Down the line, it'd be better to hunt down and eliminate all calls to\n> these functions when they are called with a zero argument.  I've already\n> added some checks for these cases that were exposed by tests.\n\nI agree that it is a bug to rely on *alloc(0) not returning\nNULL, but this patch is too risky.  It would be a good thing to\nhave debugging variant of x* wrappers that barf on a 0-byte\nallocation request to find the offending callers, instead of\nreturning NULL, maybe like the attached patch.\n\nSince eradicating *alloc(0) calls is the right way to go, but it\ntakes time.  Touching x* wrappers for general public should not\nbe done before it is done.  It breaks things for everybody,\nwhile the current code is broken only for diet people and\ndevelopers that use the debugging variant of x* wrappers.\n\n-- >8 --\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 0c98c99..08fd6bc 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -60,9 +60,17 @@ extern int gitsetenv(const char *, const\n extern char *gitstrcasestr(const char *haystack, const char *needle);\n #endif\n \n+#ifdef DEBUG_0ALLOC\n+#define debug_0alloc(sz) assert(0 < (sz))\n+#else\n+#define debug_0alloc(sz)\n+#endif\n+\n static inline void *xmalloc(size_t size)\n {\n \tvoid *ret = malloc(size);\n+\n+\tdebug_0alloc(size);\n \tif (!ret)\n \t\tdie(\"Out of memory, malloc failed\");\n \treturn ret;\n@@ -71,6 +79,7 @@ static inline void *xmalloc(size_t size)\n static inline void *xrealloc(void *ptr, size_t size)\n {\n \tvoid *ret = realloc(ptr, size);\n+\tdebug_0alloc(size);\n \tif (!ret)\n \t\tdie(\"Out of memory, realloc failed\");\n \treturn ret;\n@@ -79,6 +88,7 @@ static inline void *xrealloc(void *ptr, \n static inline void *xcalloc(size_t nmemb, size_t size)\n {\n \tvoid *ret = calloc(nmemb, size);\n+\tdebug_0alloc(nmemb);\n \tif (!ret)\n \t\tdie(\"Out of memory, calloc failed\");\n \treturn ret;\n"},{"id":"14019","messageId":"7vy82aqp5r.fsf@assigned-by-dhcp.cox.net","threadId":"2924","inReplyTo":"20051224121339.GB3963@mail.yhbt.net","subject":"Re: [PATCH 3/4] add xmktime() function that always accounts for the TZ env","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-24T19:18:56Z","receivedAt":"2005-12-24T19:18:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Wong <normalperson@yhbt.net> writes:\n\n> This function was added because mktime in dietlibc doesn't seem to\n> account for the TZ env.  Also, xmktime() now shares the same\n> always-summer bug TZ parsing elsewhere,\n\nWhere elsewhere?\n"},{"id":"14021","messageId":"20051224195247.GF3963@mail.yhbt.net","threadId":"2924","inReplyTo":"7vy82aqp5r.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 3/4] add xmktime() function that always accounts for the TZ env","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2005-12-24T19:52:47Z","receivedAt":"2005-12-24T19:52:47Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Junio C Hamano <junkio@cox.net> wrote:\n> Eric Wong <normalperson@yhbt.net> writes:\n> \n> > This function was added because mktime in dietlibc doesn't seem to\n> > account for the TZ env.  Also, xmktime() now shares the same\n> > always-summer bug TZ parsing elsewhere,\n> \n> Where elsewhere?\n \nmatch_alpha() in date.c\n\n-- \nEric Wong\n"},{"id":"14023","messageId":"7vpsnmqk0n.fsf@assigned-by-dhcp.cox.net","threadId":"2924","inReplyTo":"20051224195247.GF3963@mail.yhbt.net","subject":"Re: [PATCH 3/4] add xmktime() function that always accounts for the TZ env","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-24T21:10:00Z","receivedAt":"2005-12-24T21:10:00Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Wong <normalperson@yhbt.net> writes:\n\n> Junio C Hamano <junkio@cox.net> wrote:\n>> Eric Wong <normalperson@yhbt.net> writes:\n>> \n>> > This function was added because mktime in dietlibc doesn't seem to\n>> > account for the TZ env.  Also, xmktime() now shares the same\n>> > always-summer bug TZ parsing elsewhere,\n>> \n>> Where elsewhere?\n>  \n> match_alpha() in date.c\n\nThen probably we should extract partime.c from rcs and munge\nthat.\n"},{"id":"14024","messageId":"20051224211546.GG3963@mail.yhbt.net","threadId":"2924","inReplyTo":"7v3bkis631.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 4/4] git-compat-util.h: dietlibc-friendly x{malloc,realloc,calloc}","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2005-12-24T21:15:46Z","receivedAt":"2005-12-24T21:15:46Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Junio C Hamano <junkio@cox.net> wrote:\n> Eric Wong <normalperson@yhbt.net> writes:\n> \n> > dietlibc versions of these allocators returns NULL if a size of zero is\n> > specified.  Obviously, this is a problem with the x* wrappers since\n> > we check for them returning NULL.\n> >\n> > Down the line, it'd be better to hunt down and eliminate all calls to\n> > these functions when they are called with a zero argument.  I've already\n> > added some checks for these cases that were exposed by tests.\n> \n> I agree that it is a bug to rely on *alloc(0) not returning\n> NULL, but this patch is too risky.  It would be a good thing to\n> have debugging variant of x* wrappers that barf on a 0-byte\n> allocation request to find the offending callers, instead of\n> returning NULL, maybe like the attached patch.\n> \n> Since eradicating *alloc(0) calls is the right way to go, but it\n> takes time.  Touching x* wrappers for general public should not\n> be done before it is done.  It breaks things for everybody,\n> while the current code is broken only for diet people and\n> developers that use the debugging variant of x* wrappers.\n\nI'll be using the following patch to collect results for the next few\ndays without interrupting my work on other projects.  I'll post\npatches to remove *alloc(0) calls when I find them.\n\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 0c98c99..43be289 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -60,9 +60,41 @@ extern int gitsetenv(const char *, const\n extern char *gitstrcasestr(const char *haystack, const char *needle);\n #endif\n \n+static void fork_for_core (const char * caller)\n+{\n+\tpid_t child = fork();\n+\tif (child == 0) {\n+\t\tint i;\n+\t\tchar out[4096];\n+\t\tchar * progname = \"unknown\";\n+\t\tFILE * dbg = fopen(\"/var/tmp/git_alloc_dbg.log\",\"a\");\n+\n+\t\tfor(i = 0; environ[i]; i++) {\n+\t\t\tif (strstr(environ[i],\"_=\") == environ[i])\n+\t\t\t\tprogname = environ[i];\n+\t\t}\n+\t\t\n+\t\tsnprintf(out, 4096, \"%s:%s: pid %d dumping core for pid %d\\n\",\n+\t\t\t\tprogname, caller, getpid(), getppid());\n+\n+\t\tfputs(out, stderr);\n+\t\tfputs(out, dbg);\n+\t\tfflush(NULL);\n+\t\t\n+\t\tabort();\n+\t}\n+}\n+\n static inline void *xmalloc(size_t size)\n {\n-\tvoid *ret = malloc(size);\n+\tvoid *ret;\n+\t\n+\tif (!size) {\n+\t\tfork_for_core(__func__);\n+\t\treturn NULL;\n+\t}\n+\t\n+\tret = malloc(size);\n \tif (!ret)\n \t\tdie(\"Out of memory, malloc failed\");\n \treturn ret;\n@@ -70,7 +102,15 @@ static inline void *xmalloc(size_t size)\n \n static inline void *xrealloc(void *ptr, size_t size)\n {\n-\tvoid *ret = realloc(ptr, size);\n+\tvoid *ret;\n+\t\n+\tif (!size) {\n+\t\tfork_for_core(__func__);\n+\t\tfree(ptr);\n+\t\treturn NULL;\n+\t}\n+\t\n+\tret = realloc(ptr, size);\n \tif (!ret)\n \t\tdie(\"Out of memory, realloc failed\");\n \treturn ret;\n@@ -78,7 +118,14 @@ static inline void *xrealloc(void *ptr, \n \n static inline void *xcalloc(size_t nmemb, size_t size)\n {\n-\tvoid *ret = calloc(nmemb, size);\n+\tvoid *ret;\n+\t\n+\tif (!nmemb || !size) {\n+\t\tfork_for_core(__func__);\n+\t\treturn NULL;\n+\t}\n+\n+\tret = calloc(nmemb, size);\n \tif (!ret)\n \t\tdie(\"Out of memory, calloc failed\");\n \treturn ret;\n\n-- \nEric Wong\n"},{"id":"14043","messageId":"7v3bkflrmf.fsf@assigned-by-dhcp.cox.net","threadId":"2924","inReplyTo":"20051224121117.GB19136@mail.yhbt.net","subject":"Re: [PATCH 1/4] git.c: extra #include for dietlibc (and possibly other C libraries)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-26T17:01:28Z","receivedAt":"2005-12-26T17:01:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Wong <normalperson@yhbt.net> writes:\n\n> struct winsize is defined in <termios.h>, and that's not pulled\n> in by other #includes in that file\n\nWith glibc, sys/ioctl.h seems to pull it in.  Input from people\non other platforms is appreciated on this.\n"},{"id":"14045","messageId":"Pine.LNX.4.63.0512261916440.8435@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"2924","inReplyTo":"20051224211546.GG3963@mail.yhbt.net","subject":"[PATCH] Avoid allocating 0 bytes, was Re: [PATCH 4/4] git-compat-util.h: dietlibc-friendly x{malloc,realloc,calloc}","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2005-12-26T18:16:52Z","receivedAt":"2005-12-26T18:16:52Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThis is the result of a relatively quick audit of the source code. There\nmight still be a few odd places lurking out there, but I am quite certain\nI caught most if not all.\n\nSigned-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n\n---\n\n csum-file.c         |    3 +++\n diff.c              |    6 +++--\n diffcore-order.c    |    8 ++++++-\n diffcore-pathspec.c |   12 +++++++----\n index-pack.c        |   11 ++++++----\n pack-objects.c      |    6 ++++-\n read-tree.c         |   17 +++++++++------\n sha1_file.c         |   56 ++++++++++++++++++++++++++-------------------------\n tree-diff.c         |    4 ++++\n unpack-objects.c    |    2 +-\n 10 files changed, 76 insertions(+), 49 deletions(-)\n\n751737aeec4dd3cc1afd1d1d3fa529cfc74535e0\ndiff --git a/csum-file.c b/csum-file.c\nindex 5f9249a..2c0f097 100644\n--- a/csum-file.c\n+++ b/csum-file.c\n@@ -121,6 +121,9 @@ int sha1write_compressed(struct sha1file\n \tunsigned long maxsize;\n \tvoid *out;\n \n+\tif (size == 0)\n+\t\treturn 0;\n+\n \tmemset(&stream, 0, sizeof(stream));\n \tdeflateInit(&stream, Z_DEFAULT_COMPRESSION);\n \tmaxsize = deflateBound(&stream, size);\ndiff --git a/diff.c b/diff.c\nindex c815918..daee05b 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -504,9 +504,9 @@ static void prepare_temp_file(const char\n \t\t}\n \t\tif (S_ISLNK(st.st_mode)) {\n \t\t\tint ret;\n-\t\t\tchar *buf, buf_[1024];\n-\t\t\tbuf = ((sizeof(buf_) < st.st_size) ?\n-\t\t\t       xmalloc(st.st_size) : buf_);\n+\t\t\tchar buf[MAXPATHLEN + 1];\n+\t\t\tif (st.st_size > MAXPATHLEN)\n+\t\t\t\tdie(\"Unbelievably long symlink: %\", name);\n \t\t\tret = readlink(name, buf, st.st_size);\n \t\t\tif (ret < 0)\n \t\t\t\tdie(\"readlink(%s)\", name);\ndiff --git a/diffcore-order.c b/diffcore-order.c\nindex b381223..94a4996 100644\n--- a/diffcore-order.c\n+++ b/diffcore-order.c\n@@ -61,6 +61,8 @@ static void prepare_order(const char *or\n \t\t}\n \t\tif (pass == 0) {\n \t\t\torder_cnt = cnt;\n+\t\t\tif (cnt == 0)\n+\t\t\t\treturn;\n \t\t\torder = xmalloc(sizeof(*order) * cnt);\n \t\t}\n \t}\n@@ -105,9 +107,13 @@ static int compare_pair_order(const void\n void diffcore_order(const char *orderfile)\n {\n \tstruct diff_queue_struct *q = &diff_queued_diff;\n-\tstruct pair_order *o = xmalloc(sizeof(*o) * q->nr);\n+\tstruct pair_order *o;\n \tint i;\n \n+\tif (q->nr == 0)\n+\t\treturn;\n+\n+\to = xmalloc(sizeof(*o) * q->nr);\n \tprepare_order(orderfile);\n \tfor (i = 0; i < q->nr; i++) {\n \t\to[i].pair = q->queue[i];\ndiff --git a/diffcore-pathspec.c b/diffcore-pathspec.c\nindex 68fe009..a12337a 100644\n--- a/diffcore-pathspec.c\n+++ b/diffcore-pathspec.c\n@@ -48,10 +48,14 @@ void diffcore_pathspec(const char **path\n \tfor (i = 0; pathspec[i]; i++)\n \t\t;\n \tspeccnt = i;\n-\tspec = xmalloc(sizeof(*spec) * speccnt);\n-\tfor (i = 0; pathspec[i]; i++) {\n-\t\tspec[i].spec = pathspec[i];\n-\t\tspec[i].len = strlen(pathspec[i]);\n+\tif (speccnt == 0)\n+\t\tspec = NULL;\n+\telse {\n+\t\tspec = xmalloc(sizeof(*spec) * speccnt);\n+\t\tfor (i = 0; pathspec[i]; i++) {\n+\t\t\tspec[i].spec = pathspec[i];\n+\t\t\tspec[i].len = strlen(pathspec[i]);\n+\t\t}\n \t}\n \n \tfor (i = 0; i < q->nr; i++) {\ndiff --git a/index-pack.c b/index-pack.c\nindex d4ce3af..2927632 100644\n--- a/index-pack.c\n+++ b/index-pack.c\n@@ -103,7 +103,7 @@ static void *unpack_entry_data(unsigned \n \tunsigned long pack_limit = pack_size - 20;\n \tunsigned long pos = *current_pos;\n \tz_stream stream;\n-\tvoid *buf = xmalloc(size);\n+\tvoid *buf = xmalloc(size ? size : 1);\n \n \tmemset(&stream, 0, sizeof(stream));\n \tstream.next_out = buf;\n@@ -353,7 +353,8 @@ static void write_index_file(const char \n {\n \tstruct sha1file *f;\n \tstruct object_entry **sorted_by_sha =\n-\t\txcalloc(nr_objects, sizeof(struct object_entry *));\n+\t\txcalloc(nr_objects ? nr_objects : 1,\n+\t\t\t\tsizeof(struct object_entry *));\n \tstruct object_entry **list = sorted_by_sha;\n \tstruct object_entry **last = sorted_by_sha + nr_objects;\n \tunsigned int array[256];\n@@ -448,8 +449,10 @@ int main(int argc, char **argv)\n \n \topen_pack_file();\n \tparse_pack_header();\n-\tobjects = xcalloc(nr_objects, sizeof(struct object_entry));\n-\tdeltas = xcalloc(nr_objects, sizeof(struct delta_entry));\n+\tobjects = xcalloc(nr_objects ? nr_objects : 1,\n+\t\t\tsizeof(struct object_entry));\n+\tdeltas = xcalloc(nr_objects ? nr_objects : 1,\n+\t\t\tsizeof(struct delta_entry));\n \tparse_pack_objects();\n \tfree(deltas);\n \twrite_index_file(index_name, sha1);\ndiff --git a/pack-objects.c b/pack-objects.c\nindex caf3b6b..f5a147f 100644\n--- a/pack-objects.c\n+++ b/pack-objects.c\n@@ -406,7 +406,8 @@ static void prepare_pack(int window, int\n \n \tfprintf(stderr, \"Packing %d objects\\n\", nr_objects);\n \n-\tsorted_by_type = create_sorted_list(type_size_sort);\n+\tif (nr_objects > 0)\n+\t\tsorted_by_type = create_sorted_list(type_size_sort);\n \tif (window && depth)\n \t\tfind_deltas(sorted_by_type, window+1, depth);\n \twrite_pack_file();\n@@ -540,7 +541,8 @@ int main(int argc, char **argv)\n \tif (non_empty && !nr_objects)\n \t\treturn 0;\n \n-\tsorted_by_sha = create_sorted_list(sha1_sort);\n+\tif (nr_objects > 0)\n+\t\tsorted_by_sha = create_sorted_list(sha1_sort);\n \tSHA1_Init(&ctx);\n \tlist = sorted_by_sha;\n \tfor (i = 0; i < nr_objects; i++) {\ndiff --git a/read-tree.c b/read-tree.c\nindex e3b9c0d..a46c6fe 100644\n--- a/read-tree.c\n+++ b/read-tree.c\n@@ -294,17 +294,20 @@ static int unpack_trees(merge_fn_t fn)\n {\n \tint indpos = 0;\n \tunsigned len = object_list_length(trees);\n-\tstruct tree_entry_list **posns = \n-\t\txmalloc(len * sizeof(struct tree_entry_list *));\n+\tstruct tree_entry_list **posns;\n \tint i;\n \tstruct object_list *posn = trees;\n \tmerge_size = len;\n-\tfor (i = 0; i < len; i++) {\n-\t\tposns[i] = ((struct tree *) posn->item)->entries;\n-\t\tposn = posn->next;\n+\n+\tif (len) {\n+\t\tposns = xmalloc(len * sizeof(struct tree_entry_list *));\n+\t\tfor (i = 0; i < len; i++) {\n+\t\t\tposns[i] = ((struct tree *) posn->item)->entries;\n+\t\t\tposn = posn->next;\n+\t\t}\n+\t\tif (unpack_trees_rec(posns, len, \"\", fn, &indpos))\n+\t\t\treturn -1;\n \t}\n-\tif (unpack_trees_rec(posns, len, \"\", fn, &indpos))\n-\t\treturn -1;\n \n \tif (trivial_merges_only && nontrivial_merge)\n \t\tdie(\"Merge requires file-level merging\");\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 8bebbb2..0d60884 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -1371,35 +1371,37 @@ int write_sha1_file(void *buf, unsigned \n \t\treturn -1;\n \t}\n \n-\t/* Set it up */\n-\tmemset(&stream, 0, sizeof(stream));\n-\tdeflateInit(&stream, Z_BEST_COMPRESSION);\n-\tsize = deflateBound(&stream, len+hdrlen);\n-\tcompressed = xmalloc(size);\n-\n-\t/* Compress it */\n-\tstream.next_out = compressed;\n-\tstream.avail_out = size;\n-\n-\t/* First header.. */\n-\tstream.next_in = hdr;\n-\tstream.avail_in = hdrlen;\n-\twhile (deflate(&stream, 0) == Z_OK)\n-\t\t/* nothing */;\n-\n-\t/* Then the data itself.. */\n-\tstream.next_in = buf;\n-\tstream.avail_in = len;\n-\twhile (deflate(&stream, Z_FINISH) == Z_OK)\n-\t\t/* nothing */;\n-\tdeflateEnd(&stream);\n-\tsize = stream.total_out;\n+\tif (len + hdrlen > 0) {\n+\t\t/* Set it up */\n+\t\tmemset(&stream, 0, sizeof(stream));\n+\t\tdeflateInit(&stream, Z_BEST_COMPRESSION);\n+\t\tsize = deflateBound(&stream, len+hdrlen);\n+\t\tcompressed = xmalloc(size);\n+\n+\t\t/* Compress it */\n+\t\tstream.next_out = compressed;\n+\t\tstream.avail_out = size;\n \n-\tif (write(fd, compressed, size) != size)\n-\t\tdie(\"unable to write file\");\n+\t\t/* First header.. */\n+\t\tstream.next_in = hdr;\n+\t\tstream.avail_in = hdrlen;\n+\t\twhile (deflate(&stream, 0) == Z_OK)\n+\t\t\t/* nothing */;\n+\n+\t\t/* Then the data itself.. */\n+\t\tstream.next_in = buf;\n+\t\tstream.avail_in = len;\n+\t\twhile (deflate(&stream, Z_FINISH) == Z_OK)\n+\t\t\t/* nothing */;\n+\t\tdeflateEnd(&stream);\n+\t\tsize = stream.total_out;\n+\n+\t\tif (write(fd, compressed, size) != size)\n+\t\t\tdie(\"unable to write file\");\n+\t\tfree(compressed);\n+\t}\n \tfchmod(fd, 0444);\n \tclose(fd);\n-\tfree(compressed);\n \n \treturn move_temp_to_file(tmpfile, filename);\n }\n@@ -1429,7 +1431,7 @@ int write_sha1_to_fd(int fd, const unsig\n \t\tmemset(&stream, 0, sizeof(stream));\n \t\tdeflateInit(&stream, Z_BEST_COMPRESSION);\n \t\tsize = deflateBound(&stream, len + hdrlen);\n-\t\ttemp_obj = buf = xmalloc(size);\n+\t\ttemp_obj = buf = xmalloc(size ? size : 1);\n \n \t\t/* Compress it */\n \t\tstream.next_out = buf;\ndiff --git a/tree-diff.c b/tree-diff.c\nindex 0ef06a9..382092b 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -263,6 +263,10 @@ void diff_tree_setup_paths(const char **\n \n \t\tpaths = p;\n \t\tnr_paths = count_paths(paths);\n+\t\tif (nr_paths == 0) {\n+\t\t\tpathlens = NULL;\n+\t\t\treturn;\n+\t\t}\n \t\tpathlens = xmalloc(nr_paths * sizeof(int));\n \t\tfor (i=0; i<nr_paths; i++)\n \t\t\tpathlens[i] = strlen(paths[i]);\ndiff --git a/unpack-objects.c b/unpack-objects.c\nindex 5c5cb12..572eeee 100644\n--- a/unpack-objects.c\n+++ b/unpack-objects.c\n@@ -53,7 +53,7 @@ static void use(int bytes)\n static void *get_data(unsigned long size)\n {\n \tz_stream stream;\n-\tvoid *buf = xmalloc(size);\n+\tvoid *buf = xmalloc(size ? size : 1);\n \n \tmemset(&stream, 0, sizeof(stream));\n \n-- \n1.0.GIT\n"},{"id":"14046","messageId":"7vzmmnisix.fsf@assigned-by-dhcp.cox.net","threadId":"2924","inReplyTo":"Pine.LNX.4.63.0512261916440.8435@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] Avoid allocating 0 bytes, was Re: [PATCH 4/4] git-compat-util.h: dietlibc-friendly x{malloc,realloc,calloc}","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-26T19:10:14Z","receivedAt":"2005-12-26T19:10:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> This is the result of a relatively quick audit of the source code. There\n> might still be a few odd places lurking out there, but I am quite certain\n> I caught most if not all.\n\nThanks.\n\n> diff --git a/csum-file.c b/csum-file.c\n> index 5f9249a..2c0f097 100644\n> --- a/csum-file.c\n> +++ b/csum-file.c\n> @@ -121,6 +121,9 @@ int sha1write_compressed(struct sha1file\n>  \tunsigned long maxsize;\n>  \tvoid *out;\n>  \n> +\tif (size == 0)\n> +\t\treturn 0;\n> +\n>  \tmemset(&stream, 0, sizeof(stream));\n>  \tdeflateInit(&stream, Z_DEFAULT_COMPRESSION);\n>  \tmaxsize = deflateBound(&stream, size);\n\nI think this and the one in sha1_file.c::write_sha1_file() are\nwrong; 0-size input would not result in 0-size output.  Have you\ntested them by actually exercising the codepaths you touched?\n\n> diff --git a/diffcore-pathspec.c b/diffcore-pathspec.c\n> index 68fe009..a12337a 100644\n> --- a/diffcore-pathspec.c\n> +++ b/diffcore-pathspec.c\n> @@ -48,10 +48,14 @@ void diffcore_pathspec(const char **path\n\ndiffcore-pathspec and diffcore-order can probably return without\ntouching diff_queued_diff if there is no work to be done.\n\n> @@ -353,7 +353,8 @@ static void write_index_file(const char \n>  {\n>  \tstruct sha1file *f;\n>  \tstruct object_entry **sorted_by_sha =\n> -\t\txcalloc(nr_objects, sizeof(struct object_entry *));\n> +\t\txcalloc(nr_objects ? nr_objects : 1,\n> +\t\t\t\tsizeof(struct object_entry *));\n>  \tstruct object_entry **list = sorted_by_sha;\n>  \tstruct object_entry **last = sorted_by_sha + nr_objects;\n>  \tunsigned int array[256];\n\nThis can be simplified by sorted_by_sha = list = last = NULL\nwhen nr_objects == 0 and avoiding qsort; that is what you did in\npack-objects, I think.\n\n> @@ -448,8 +449,10 @@ int main(int argc, char **argv)\n>  \n>  \topen_pack_file();\n>  \tparse_pack_header();\n> -\tobjects = xcalloc(nr_objects, sizeof(struct object_entry));\n> -\tdeltas = xcalloc(nr_objects, sizeof(struct delta_entry));\n> +\tobjects = xcalloc(nr_objects ? nr_objects : 1,\n> +\t\t\tsizeof(struct object_entry));\n> +\tdeltas = xcalloc(nr_objects ? nr_objects : 1,\n> +\t\t\tsizeof(struct delta_entry));\n>  \tparse_pack_objects();\n>  \tfree(deltas);\n>  \twrite_index_file(index_name, sha1);\n\nLikewise I suspect.  After all the special case is only when\nreindexing an empty pack ;-).\n\nMy inclination is to do things in these steps:\n\n - apply cleanups that actually simplify the logic, while\n   leaving the ones that you needed to do (size ?  size : 1)\n   unmodified (BTW, must next_in/next_out point at non NULL when\n   avail_in/avail_out are zero?).\n\n - change x*alloc like this, once the above is done:\n\n        static inline void *xmalloc(size_t size)\n        {\n                void *ret = malloc(size);\n        #ifdef MALLOC_CAN_RETURN_NULL_ON_0SIZE\n                if (!ret && !size)\n                        ret = malloc(size+1);\n        #endif\n                if (!ret)\n                        die(\"Out of memory, malloc failed\");\n                return ret;\n        }\n"},{"id":"14047","messageId":"Pine.LNX.4.63.0512262134290.19331@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"2924","inReplyTo":"7vzmmnisix.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Avoid allocating 0 bytes, was Re: [PATCH 4/4] git-compat-util.h: dietlibc-friendly x{malloc,realloc,calloc}","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2005-12-26T20:34:41Z","receivedAt":"2005-12-26T20:34:41Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 26 Dec 2005, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > diff --git a/csum-file.c b/csum-file.c\n> > index 5f9249a..2c0f097 100644\n> > --- a/csum-file.c\n> > +++ b/csum-file.c\n> > @@ -121,6 +121,9 @@ int sha1write_compressed(struct sha1file\n> >  \tunsigned long maxsize;\n> >  \tvoid *out;\n> >  \n> > +\tif (size == 0)\n> > +\t\treturn 0;\n> > +\n> >  \tmemset(&stream, 0, sizeof(stream));\n> >  \tdeflateInit(&stream, Z_DEFAULT_COMPRESSION);\n> >  \tmaxsize = deflateBound(&stream, size);\n> \n> I think this and the one in sha1_file.c::write_sha1_file() are\n> wrong; 0-size input would not result in 0-size output.  Have you\n> tested them by actually exercising the codepaths you touched?\n\nNo, I did not test them. At least not consciously (I did the whole work on \nDec 24, when I was lying in bed, ill, trying to distract myself from being \nmiserable).\n\nThe reason I did it this way: If zlib inflates a buffer of 0 bytes, it \nmakes no sense to expect anything than 0 bytes to come out of it, right? \nTherefore, if zlib encounters a deflated buffer of 0 bytes, it should \ninflate it to 0 bytes. So it is a good idea in any case to write out 0 \nbytes.\n\nHowever, thinking of it again, it might break backwards compatibility. But \nI don't think so.\n\n> > diff --git a/diffcore-pathspec.c b/diffcore-pathspec.c\n> > index 68fe009..a12337a 100644\n> > --- a/diffcore-pathspec.c\n> > +++ b/diffcore-pathspec.c\n> > @@ -48,10 +48,14 @@ void diffcore_pathspec(const char **path\n> \n> diffcore-pathspec and diffcore-order can probably return without\n> touching diff_queued_diff if there is no work to be done.\n\nTo be honest: I did not completely understand what that code does. \nIt seemed obvious, but I got a track record of breaking things. So I was \ncautious. I will not try to modify it myself without a good test case.\n\n> > @@ -353,7 +353,8 @@ static void write_index_file(const char \n> >  {\n> >  \tstruct sha1file *f;\n> >  \tstruct object_entry **sorted_by_sha =\n> > -\t\txcalloc(nr_objects, sizeof(struct object_entry *));\n> > +\t\txcalloc(nr_objects ? nr_objects : 1,\n> > +\t\t\t\tsizeof(struct object_entry *));\n> >  \tstruct object_entry **list = sorted_by_sha;\n> >  \tstruct object_entry **last = sorted_by_sha + nr_objects;\n> >  \tunsigned int array[256];\n> \n> This can be simplified by sorted_by_sha = list = last = NULL\n> when nr_objects == 0 and avoiding qsort; that is what you did in\n> pack-objects, I think.\n\nIf nr_objects == 0, we could write out a fixed index.\n\nWe could alternatively exit(1), because what sense does it make to have an \nindex if the pack contains 0 objects? However, this has consequences: \nEvery user of index-pack (does \"fetch-pack --keep\" call it?) has to be \naware that empty packs are illegal.\n\nAgain, I did this so that the tool does not break. I'll try to come up \nwith something better soon.\n\n> > @@ -448,8 +449,10 @@ int main(int argc, char **argv)\n> >  \n> >  \topen_pack_file();\n> >  \tparse_pack_header();\n> > -\tobjects = xcalloc(nr_objects, sizeof(struct object_entry));\n> > -\tdeltas = xcalloc(nr_objects, sizeof(struct delta_entry));\n> > +\tobjects = xcalloc(nr_objects ? nr_objects : 1,\n> > +\t\t\tsizeof(struct object_entry));\n> > +\tdeltas = xcalloc(nr_objects ? nr_objects : 1,\n> > +\t\t\tsizeof(struct delta_entry));\n> >  \tparse_pack_objects();\n> >  \tfree(deltas);\n> >  \twrite_index_file(index_name, sha1);\n> \n> Likewise I suspect.  After all the special case is only when\n> reindexing an empty pack ;-).\n\nRight.\n\n> My inclination is to do things in these steps:\n> \n>  - apply cleanups that actually simplify the logic, while\n>    leaving the ones that you needed to do (size ?  size : 1)\n>    unmodified (BTW, must next_in/next_out point at non NULL when\n>    avail_in/avail_out are zero?).\n\nI was cautious. Maybe at some point in future, zlib relies on that. But it \nis probably better to try not calling zlib at all in these cases.\n\n>  - change x*alloc like this, once the above is done:\n> \n>         static inline void *xmalloc(size_t size)\n>         {\n>                 void *ret = malloc(size);\n>         #ifdef MALLOC_CAN_RETURN_NULL_ON_0SIZE\n>                 if (!ret && !size)\n>                         ret = malloc(size+1);\n>         #endif\n>                 if (!ret)\n>                         die(\"Out of memory, malloc failed\");\n>                 return ret;\n>         }\n\nSounds easiest.\n\nCiao,\nDscho\n"},{"id":"14049","messageId":"7vslsfikii.fsf_-_@assigned-by-dhcp.cox.net","threadId":"2924","inReplyTo":"Pine.LNX.4.63.0512262134290.19331@wbgn013.biozentrum.uni-wuerzburg.de","subject":"[PATCH] avoid asking ?alloc() for zero bytes.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-26T22:03:17Z","receivedAt":"2005-12-26T22:03:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Avoid asking for zero bytes when that change simplifies overall\nlogic.  Later we would change the wrapper to ask for 1 byte on\nplatforms that return NULL for zero byte request.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n * Here is what I have now that roughly corresponds to your\n   patch, which has been somewhat tested.\n\n   The final phase of making sure we return something from\n   x*alloc() is not done yet.\n\n diff.c              |    6 +++---\n diffcore-order.c    |    6 +++++-\n diffcore-pathspec.c |    3 +++\n index-pack.c        |   22 ++++++++++++++--------\n read-tree.c         |   17 ++++++++++-------\n tree-diff.c         |    4 ++++\n 6 files changed, 39 insertions(+), 19 deletions(-)\n\nda95c79803d90ce8eaf82b0c04dbde11c096ad87\ndiff --git a/diff.c b/diff.c\nindex c815918..bfc864d 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -504,9 +504,9 @@ static void prepare_temp_file(const char\n \t\t}\n \t\tif (S_ISLNK(st.st_mode)) {\n \t\t\tint ret;\n-\t\t\tchar *buf, buf_[1024];\n-\t\t\tbuf = ((sizeof(buf_) < st.st_size) ?\n-\t\t\t       xmalloc(st.st_size) : buf_);\n+\t\t\tchar buf[PATH_MAX + 1]; /* ought to be SYMLINK_MAX */\n+\t\t\tif (sizeof(buf) <= st.st_size)\n+\t\t\t\tdie(\"symlink too long: %s\", name);\n \t\t\tret = readlink(name, buf, st.st_size);\n \t\t\tif (ret < 0)\n \t\t\t\tdie(\"readlink(%s)\", name);\ndiff --git a/diffcore-order.c b/diffcore-order.c\nindex b381223..0bc2b22 100644\n--- a/diffcore-order.c\n+++ b/diffcore-order.c\n@@ -105,9 +105,13 @@ static int compare_pair_order(const void\n void diffcore_order(const char *orderfile)\n {\n \tstruct diff_queue_struct *q = &diff_queued_diff;\n-\tstruct pair_order *o = xmalloc(sizeof(*o) * q->nr);\n+\tstruct pair_order *o;\n \tint i;\n \n+\tif (!q->nr)\n+\t\treturn;\n+\n+\to = xmalloc(sizeof(*o) * q->nr);\n \tprepare_order(orderfile);\n \tfor (i = 0; i < q->nr; i++) {\n \t\to[i].pair = q->queue[i];\ndiff --git a/diffcore-pathspec.c b/diffcore-pathspec.c\nindex 68fe009..139fe88 100644\n--- a/diffcore-pathspec.c\n+++ b/diffcore-pathspec.c\n@@ -48,6 +48,9 @@ void diffcore_pathspec(const char **path\n \tfor (i = 0; pathspec[i]; i++)\n \t\t;\n \tspeccnt = i;\n+\tif (!speccnt)\n+\t\treturn;\n+\n \tspec = xmalloc(sizeof(*spec) * speccnt);\n \tfor (i = 0; pathspec[i]; i++) {\n \t\tspec[i].spec = pathspec[i];\ndiff --git a/index-pack.c b/index-pack.c\nindex d4ce3af..541d7bc 100644\n--- a/index-pack.c\n+++ b/index-pack.c\n@@ -352,18 +352,24 @@ static int sha1_compare(const void *_a, \n static void write_index_file(const char *index_name, unsigned char *sha1)\n {\n \tstruct sha1file *f;\n-\tstruct object_entry **sorted_by_sha =\n-\t\txcalloc(nr_objects, sizeof(struct object_entry *));\n-\tstruct object_entry **list = sorted_by_sha;\n-\tstruct object_entry **last = sorted_by_sha + nr_objects;\n+\tstruct object_entry **sorted_by_sha, **list, **last;\n \tunsigned int array[256];\n \tint i;\n \tSHA_CTX ctx;\n \n-\tfor (i = 0; i < nr_objects; ++i)\n-\t\tsorted_by_sha[i] = &objects[i];\n-\tqsort(sorted_by_sha, nr_objects, sizeof(sorted_by_sha[0]),\n-\t      sha1_compare);\n+\tif (nr_objects) {\n+\t\tsorted_by_sha =\n+\t\t\txcalloc(nr_objects, sizeof(struct object_entry *));\n+\t\tlist = sorted_by_sha;\n+\t\tlast = sorted_by_sha + nr_objects;\n+\t\tfor (i = 0; i < nr_objects; ++i)\n+\t\t\tsorted_by_sha[i] = &objects[i];\n+\t\tqsort(sorted_by_sha, nr_objects, sizeof(sorted_by_sha[0]),\n+\t\t      sha1_compare);\n+\n+\t}\n+\telse\n+\t\tsorted_by_sha = list = last = NULL;\n \n \tunlink(index_name);\n \tf = sha1create(\"%s\", index_name);\ndiff --git a/read-tree.c b/read-tree.c\nindex e3b9c0d..a46c6fe 100644\n--- a/read-tree.c\n+++ b/read-tree.c\n@@ -294,17 +294,20 @@ static int unpack_trees(merge_fn_t fn)\n {\n \tint indpos = 0;\n \tunsigned len = object_list_length(trees);\n-\tstruct tree_entry_list **posns = \n-\t\txmalloc(len * sizeof(struct tree_entry_list *));\n+\tstruct tree_entry_list **posns;\n \tint i;\n \tstruct object_list *posn = trees;\n \tmerge_size = len;\n-\tfor (i = 0; i < len; i++) {\n-\t\tposns[i] = ((struct tree *) posn->item)->entries;\n-\t\tposn = posn->next;\n+\n+\tif (len) {\n+\t\tposns = xmalloc(len * sizeof(struct tree_entry_list *));\n+\t\tfor (i = 0; i < len; i++) {\n+\t\t\tposns[i] = ((struct tree *) posn->item)->entries;\n+\t\t\tposn = posn->next;\n+\t\t}\n+\t\tif (unpack_trees_rec(posns, len, \"\", fn, &indpos))\n+\t\t\treturn -1;\n \t}\n-\tif (unpack_trees_rec(posns, len, \"\", fn, &indpos))\n-\t\treturn -1;\n \n \tif (trivial_merges_only && nontrivial_merge)\n \t\tdie(\"Merge requires file-level merging\");\ndiff --git a/tree-diff.c b/tree-diff.c\nindex 0ef06a9..382092b 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -263,6 +263,10 @@ void diff_tree_setup_paths(const char **\n \n \t\tpaths = p;\n \t\tnr_paths = count_paths(paths);\n+\t\tif (nr_paths == 0) {\n+\t\t\tpathlens = NULL;\n+\t\t\treturn;\n+\t\t}\n \t\tpathlens = xmalloc(nr_paths * sizeof(int));\n \t\tfor (i=0; i<nr_paths; i++)\n \t\t\tpathlens[i] = strlen(paths[i]);\n-- \n1.0.GIT\n"},{"id":"14050","messageId":"Pine.LNX.4.63.0512262316150.32161@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"2924","inReplyTo":"7vslsfikii.fsf_-_@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] avoid asking ?alloc() for zero bytes.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2005-12-26T22:18:03Z","receivedAt":"2005-12-26T22:18:03Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 26 Dec 2005, Junio C Hamano wrote:\n\n> Avoid asking for zero bytes when that change simplifies overall\n> logic.  Later we would change the wrapper to ask for 1 byte on\n> platforms that return NULL for zero byte request.\n> \n> Signed-off-by: Junio C Hamano <junkio@cox.net>\n> \n> ---\n> \n>  * Here is what I have now that roughly corresponds to your\n>    patch, which has been somewhat tested.\n\nThanks.\n\n>    The final phase of making sure we return something from\n>    x*alloc() is not done yet.\n\nTomorrow I'll compare the two patches and find out what, if anything, is \nneeded.\n\nCiao,\nDscho\n"},{"id":"14080","messageId":"43B21312.50603@zytor.com","threadId":"2924","inReplyTo":"20051224121243.GA3963@mail.yhbt.net","subject":"Re: [PATCH 2/4] short circuit out of a few places where we would allocate zero bytes","fromName":"H. Peter Anvin","fromEmail":"hpa@zytor.com","sentAt":"2005-12-28T04:22:42Z","receivedAt":"2005-12-28T04:22:42Z","isPatch":true,"sender":{"key":"hpa@zytor.com","avatar":null},"body":"Eric Wong wrote:\n> dietlibc versions of malloc, calloc and realloc all return NULL if\n> they're told to allocate 0 bytes, causes the x* wrappers to die().\n> \n> There are several more places where these calls could end up asking\n> for 0 bytes, too...\n> \n> Maybe simply not die()-ing in the x* wrappers if 0/NULL is returned\n> when the requested size is zero is a safer and easier way to go.\n> \n\nBetter yet, either always return NULL or allocate 1 byte in that case, \nto get consistent behaviour.\n\n\t-hpa\n"},{"id":"14081","messageId":"Pine.LNX.4.64.0512272036380.14098@g5.osdl.org","threadId":"2924","inReplyTo":"43B21312.50603@zytor.com","subject":"Re: [PATCH 2/4] short circuit out of a few places where we would allocate zero bytes","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-12-28T04:38:10Z","receivedAt":"2005-12-28T04:38:10Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 27 Dec 2005, H. Peter Anvin wrote:\n> \n> Better yet, either always return NULL or allocate 1 byte in that case, to get\n> consistent behaviour.\n\nYes. However, if you do the \"return NULL\" case (which is nicest), you'll \nhave to wrap \"free()\" too. There are some libraries where passing \"free()\" \na NULL pointer causes a SIGSEGV.\n\nThat said, I think that would be preferable to changing the source code to \nunnecessarily avoid zero-sized allocations. Having a \"xfree()\" to match \n\"xmalloc()\" makes sense. \n\n\t\tLinus\n"},{"id":"14082","messageId":"7vpsnh24j3.fsf@assigned-by-dhcp.cox.net","threadId":"2924","inReplyTo":"Pine.LNX.4.64.0512272036380.14098@g5.osdl.org","subject":"Re: [PATCH 2/4] short circuit out of a few places where we would allocate zero bytes","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-28T05:07:28Z","receivedAt":"2005-12-28T05:07:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> That said, I think that would be preferable to changing the source code to \n> unnecessarily avoid zero-sized allocations.\n\nYes, that has essentially been the plan (according to the\ndiscussion lead to 7e4a2a848377241b8fb4f624d1151bbf2f8d5814\ncommit on the list).\n\nAfter eradicating zero-sized allocations where that change makes\nthe overall code cleaner (which Johannes and Eric did most of\nthe heavylifting and I think mostly done), we would apply\nsomething like this, instead of doing x*alloc(size ? size : 1)\nat the calling site.\n\nAbout die(), I think the current code structure is fine.  If we\nwere doing a library, propagating NULL from C library *alloc()\nback to our caller and having the caller deal with it is the\nright thing, but most of the callers of x*alloc() are our main\nprograms and there aren't much they can do when we run out of\nmemory.\n\n---\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 0c98c99..a71728e 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -63,6 +63,8 @@ extern char *gitstrcasestr(const char *h\n static inline void *xmalloc(size_t size)\n {\n \tvoid *ret = malloc(size);\n+\tif (!ret && !size)\n+\t\tret = malloc(1); /* funny c library */\n \tif (!ret)\n \t\tdie(\"Out of memory, malloc failed\");\n \treturn ret;\n@@ -71,6 +73,8 @@ static inline void *xmalloc(size_t size)\n static inline void *xrealloc(void *ptr, size_t size)\n {\n \tvoid *ret = realloc(ptr, size);\n+\tif (!ret && !size)\n+\t\tret = realloc(ptr, 1); /* funny c library */\n \tif (!ret)\n \t\tdie(\"Out of memory, realloc failed\");\n \treturn ret;\n@@ -79,6 +83,8 @@ static inline void *xrealloc(void *ptr, \n static inline void *xcalloc(size_t nmemb, size_t size)\n {\n \tvoid *ret = calloc(nmemb, size);\n+\tif (!ret && (!nmemb || !size))\n+\t\tret = calloc(1, 1); /* funny c library */\n \tif (!ret)\n \t\tdie(\"Out of memory, calloc failed\");\n \treturn ret;\n"},{"id":"14091","messageId":"43B2C44B.1070102@zytor.com","threadId":"2924","inReplyTo":"Pine.LNX.4.64.0512272036380.14098@g5.osdl.org","subject":"Re: [PATCH 2/4] short circuit out of a few places where we would allocate zero bytes","fromName":"H. Peter Anvin","fromEmail":"hpa@zytor.com","sentAt":"2005-12-28T16:58:51Z","receivedAt":"2005-12-28T16:58:51Z","isPatch":true,"sender":{"key":"hpa@zytor.com","avatar":null},"body":"Linus Torvalds wrote:\n> \n> On Tue, 27 Dec 2005, H. Peter Anvin wrote:\n> \n>>Better yet, either always return NULL or allocate 1 byte in that case, to get\n>>consistent behaviour.\n> \n> Yes. However, if you do the \"return NULL\" case (which is nicest), you'll \n> have to wrap \"free()\" too. There are some libraries where passing \"free()\" \n> a NULL pointer causes a SIGSEGV.\n> \n> That said, I think that would be preferable to changing the source code to \n> unnecessarily avoid zero-sized allocations. Having a \"xfree()\" to match \n> \"xmalloc()\" makes sense. \n> \n\nYeah, although that might break GNU code which uses xmalloc that is \nincluded (GNU doesn't have xfree.)  The easiest is just to allocate 1 \nbyte when the user asks for 0.\n\nAnyone knows what GNU xmalloc does?\n\n\t-hpa\n"},{"id":"14092","messageId":"Pine.LNX.4.63.0512282134380.2236@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"2924","inReplyTo":"Pine.LNX.4.63.0512262134290.19331@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] Avoid allocating 0 bytes, was Re: [PATCH 4/4] git-compat-util.h: dietlibc-friendly x{malloc,realloc,calloc}","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2005-12-28T20:38:32Z","receivedAt":"2005-12-28T20:38:32Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 26 Dec 2005, Johannes Schindelin wrote:\n\n> On Mon, 26 Dec 2005, Junio C Hamano wrote:\n> \n> > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> > \n> > > diff --git a/csum-file.c b/csum-file.c\n> > > index 5f9249a..2c0f097 100644\n> > > --- a/csum-file.c\n> > > +++ b/csum-file.c\n> > > @@ -121,6 +121,9 @@ int sha1write_compressed(struct sha1file\n> > >  \tunsigned long maxsize;\n> > >  \tvoid *out;\n> > >  \n> > > +\tif (size == 0)\n> > > +\t\treturn 0;\n> > > +\n> > >  \tmemset(&stream, 0, sizeof(stream));\n> > >  \tdeflateInit(&stream, Z_DEFAULT_COMPRESSION);\n> > >  \tmaxsize = deflateBound(&stream, size);\n> > \n> > I think this and the one in sha1_file.c::write_sha1_file() are\n> > wrong; 0-size input would not result in 0-size output.  Have you\n> > tested them by actually exercising the codepaths you touched?\n> \n> No, I did not test them.\n\nNow I did. To make a long story short: this patch is wrong, wrong, wrong. \nFurther, I think it is safe to assume that deflateBound() returns > 0.\n\nCiao,\nDscho\n"},{"id":"14107","messageId":"20051230230035.GA7165@mail.yhbt.net","threadId":"2924","inReplyTo":"Pine.LNX.4.63.0512261916440.8435@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] Avoid allocating 0 bytes, was Re: [PATCH 4/4] git-compat-util.h: dietlibc-friendly x{malloc,realloc,calloc}","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2005-12-30T23:00:35Z","receivedAt":"2005-12-30T23:00:35Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> diff --git a/index-pack.c b/index-pack.c\n> index d4ce3af..2927632 100644\n> --- a/index-pack.c\n> +++ b/index-pack.c\n> @@ -103,7 +103,7 @@ static void *unpack_entry_data(unsigned \n>  \tunsigned long pack_limit = pack_size - 20;\n>  \tunsigned long pos = *current_pos;\n>  \tz_stream stream;\n> -\tvoid *buf = xmalloc(size);\n> +\tvoid *buf = xmalloc(size ? size : 1);\n>  \n>  \tmemset(&stream, 0, sizeof(stream));\n>  \tstream.next_out = buf;\n\nThis is the only one I've managed to hit upon further use the past week\nof usage.  No way to break out of the function, either, because\ncurrent_pos needs to be updated (and it is changed despite a zero-byte\nblob object being in my repository).\n\n-- \nEric Wong\n"}]}