@matheusbsbs / matheus-bagliano / commits / c4582f93a2
Fork 0

Add compat/snprintf.c for systems that return bogus

Some systems (namely HPUX and Windows) return -1 when maxsize in snprintf() and in vsnprintf() is reached. So replace snprintf() and vsnprintf() functions with our own ones that return correct value upon overflow. [jc: verified that review comments by J6t have been incorporated, and tightened the check to verify the resulting buffer contents, suggested by Wayne Davison] Signed-off-by: Michal Rokos <michal.rokos@nextsoft.cz> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michal Rokos committed Mar 5, 2008 at 16:46 UTC c4582f93a263bea534288e7f7ad8937405964cd4
5 files changed +92
Makefile
+8
@@ -3,6 +3,10 @@ all::
3
4 # Define V=1 to have a more verbose compile.
5 #
6 +# Define SNPRINTF_RETURNS_BOGUS if your are on a system which snprintf()
7 +# or vsnprintf() return -1 instead of number of characters which would
8 +# have been written to the final string if enough space had been available.
9 +#
10 # Define FREAD_READS_DIRECTORIES if your are on a system which succeeds
11 # when attempting to read from an fopen'ed directory.
12 #
@@ -629,6 +633,10 @@ endif
633 ifdef NO_C99_FORMAT
634 BASIC_CFLAGS += -DNO_C99_FORMAT
635 endif
636 +ifdef SNPRINTF_RETURNS_BOGUS
637 + COMPAT_CFLAGS += -DSNPRINTF_RETURNS_BOGUS
638 + COMPAT_OBJS += compat/snprintf.o
639 +endif
640 ifdef FREAD_READS_DIRECTORIES
641 COMPAT_CFLAGS += -DFREAD_READS_DIRECTORIES
642 COMPAT_OBJS += compat/fopen.o
compat/snprintf.c new
+40
@@ -0,0 +1,40 @@
1 +#include "../git-compat-util.h"
2 +
3 +#undef vsnprintf
4 +int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)
5 +{
6 + char *s;
7 + int ret;
8 +
9 + ret = vsnprintf(str, maxsize, format, ap);
10 + if (ret != -1)
11 + return ret;
12 +
13 + s = NULL;
14 + if (maxsize < 128)
15 + maxsize = 128;
16 +
17 + while (ret == -1) {
18 + maxsize *= 4;
19 + str = realloc(s, maxsize);
20 + if (! str)
21 + break;
22 + s = str;
23 + ret = vsnprintf(str, maxsize, format, ap);
24 + }
25 + free(s);
26 + return ret;
27 +}
28 +
29 +int git_snprintf(char *str, size_t maxsize, const char *format, ...)
30 +{
31 + va_list ap;
32 + int ret;
33 +
34 + va_start(ap, format);
35 + ret = git_vsnprintf(str, maxsize, format, ap);
36 + va_end(ap);
37 +
38 + return ret;
39 +}
40 +
config.mak.in
+1
@@ -46,3 +46,4 @@ NO_MKDTEMP=@NO_MKDTEMP@
46 NO_ICONV=@NO_ICONV@
47 OLD_ICONV=@OLD_ICONV@
48 NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@
49 +SNPRINTF_RETURNS_BOGUS=@SNPRINTF_RETURNS_BOGUS@
configure.ac
+34
@@ -326,6 +326,40 @@ else
326 NO_C99_FORMAT=
327 fi
328 AC_SUBST(NO_C99_FORMAT)
329 +#
330 +# Define SNPRINTF_RETURNS_BOGUS if your are on a system which snprintf()
331 +# or vsnprintf() return -1 instead of number of characters which would
332 +# have been written to the final string if enough space had been available.
333 +AC_CACHE_CHECK([whether snprintf() and/or vsnprintf() return bogus value],
334 + [ac_cv_snprintf_returns_bogus],
335 +[
336 +AC_RUN_IFELSE(
337 + [AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
338 + #include "stdarg.h"
339 +
340 + int test_vsnprintf(char *str, size_t maxsize, const char *format, ...)
341 + {
342 + int ret;
343 + va_list ap;
344 + va_start(ap, format);
345 + ret = vsnprintf(str, maxsize, format, ap);
346 + va_end(ap);
347 + return ret;
348 + }],
349 + [[char buf[6];
350 + if (test_vsnprintf(buf, 3, "%s", "12345") != 5
351 + || strcmp(buf, "12")) return 1;
352 + if (snprintf(buf, 3, "%s", "12345") != 5
353 + || strcmp(buf, "12")) return 1]])],
354 + [ac_cv_snprintf_returns_bogus=no],
355 + [ac_cv_snprintf_returns_bogus=yes])
356 +])
357 +if test $ac_cv_snprintf_returns_bogus = yes; then
358 + SNPRINTF_RETURNS_BOGUS=UnfortunatelyYes
359 +else
360 + SNPRINTF_RETURNS_BOGUS=
361 +fi
362 +AC_SUBST(SNPRINTF_RETURNS_BOGUS)
363
364
365 ## Checks for library functions.
git-compat-util.h
+9
@@ -209,6 +209,15 @@ void *gitmemmem(const void *haystack, size_t haystacklen,
209 extern FILE *git_fopen(const char*, const char*);
210 #endif
211
212 +#ifdef SNPRINTF_RETURNS_BOGUS
213 +#define snprintf git_snprintf
214 +extern int git_snprintf(char *str, size_t maxsize,
215 + const char *format, ...);
216 +#define vsnprintf git_vsnprintf
217 +extern int git_vsnprintf(char *str, size_t maxsize,
218 + const char *format, va_list ap);
219 +#endif
220 +
221 #ifdef __GLIBC_PREREQ
222 #if __GLIBC_PREREQ(2, 1)
223 #define HAVE_STRCHRNUL