From 7f09977ea61ee8ca2a74a6948f3bedb0cfae01cb Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Sun, 22 Dec 2019 15:09:21 +0100 Subject: [PATCH] compat/snprintf: keep errno across function call The incarnation of vsnprintf that I have to use requires our replacement from vsnprintf, because it returns -1 when the resulting string does not fit into the supplied buffer. An additional behavior is that it returns ERANGE when this overflow happens. There seem to be code paths in the Windows compatibility layer where a usable errno value is turned into ERANGE. A symptom is that in t0410-partial-clone.sh I observe ++ git -C repo fsck Checking object directories: 100% (256/256), done. Checking objects: 100% (1/1), done. fatal: failed to read object 3836707...snip...6591523: Result too large where the expected result is Checking object directories: 100% (256/256), done. Checking objects: 100% (1/1), done. dangling tag e5f4cb9fd329c512b08fb81a8e6b1f5e27658263 There are other cases where the wrong error happens as well: t0000-basic.sh t5310-pack-bitmaps.sh t5318-commit-graph.sh t5500-fetch-pack.sh t5616-partial-clone.sh t6050-replace.sh t6501-freshen-objects.sh Unfortunately, due to a lacking tool chain, I am unable to dig into the root cause of the problem. So, let's do the second best thing: ensure that errno is preserved across the compatibility vsnprintf. Signed-off-by: Johannes Sixt --- compat/snprintf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compat/snprintf.c b/compat/snprintf.c index 0b116885377881..bbed4345e3f522 100644 --- a/compat/snprintf.c +++ b/compat/snprintf.c @@ -22,6 +22,7 @@ int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap) va_list cp; char *s; int ret = -1; + int save_errno = errno; if (maxsize > 0) { va_copy(cp, ap); @@ -33,7 +34,7 @@ int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap) str[maxsize-1] = 0; } if (ret != -1) - return ret; + goto out; s = NULL; if (maxsize < 128) @@ -52,6 +53,8 @@ int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap) ret = -1; } free(s); +out: + errno = save_errno; return ret; }