Skip to content

Commit c4582f9

Browse files
Michal Rokosgitster
authored andcommitted
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>
1 parent b921764 commit c4582f9

File tree

5 files changed

+92
-0
lines changed

5 files changed

+92
-0
lines changed

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ all::
33

44
# Define V=1 to have a more verbose compile.
55
#
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+
#
610
# Define FREAD_READS_DIRECTORIES if your are on a system which succeeds
711
# when attempting to read from an fopen'ed directory.
812
#
@@ -629,6 +633,10 @@ endif
629633
ifdef NO_C99_FORMAT
630634
BASIC_CFLAGS += -DNO_C99_FORMAT
631635
endif
636+
ifdef SNPRINTF_RETURNS_BOGUS
637+
COMPAT_CFLAGS += -DSNPRINTF_RETURNS_BOGUS
638+
COMPAT_OBJS += compat/snprintf.o
639+
endif
632640
ifdef FREAD_READS_DIRECTORIES
633641
COMPAT_CFLAGS += -DFREAD_READS_DIRECTORIES
634642
COMPAT_OBJS += compat/fopen.o

compat/snprintf.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,4 @@ NO_MKDTEMP=@NO_MKDTEMP@
4646
NO_ICONV=@NO_ICONV@
4747
OLD_ICONV=@OLD_ICONV@
4848
NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@
49+
SNPRINTF_RETURNS_BOGUS=@SNPRINTF_RETURNS_BOGUS@

configure.ac

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,40 @@ else
326326
NO_C99_FORMAT=
327327
fi
328328
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)
329363

330364

331365
## Checks for library functions.

git-compat-util.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,15 @@ void *gitmemmem(const void *haystack, size_t haystacklen,
209209
extern FILE *git_fopen(const char*, const char*);
210210
#endif
211211

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+
212221
#ifdef __GLIBC_PREREQ
213222
#if __GLIBC_PREREQ(2, 1)
214223
#define HAVE_STRCHRNUL

0 commit comments

Comments
 (0)