[PATCH v2] Add compat/snprintf.c for systems that return bogus
From: Michal Rokos <hidden>
Date: 2016-06-15 22:44:20
Subsystem:
kernel build + files below scripts/ (unless maintained elsewhere), the rest · Maintainers:
Nathan Chancellor, Nicolas Schier, Linus Torvalds
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. Signed-off-by: Michal Rokos <redacted>
diff --git a/Makefile b/Makefile
index ca5aad9..6af7132 100644
--- a/Makefile
+++ b/Makefile@@ -3,6 +3,10 @@ all:: # Define V=1 to have a more verbose compile. # +# Define SNPRINTF_RETURNS_BOGUS if your are on a system which snprintf() +# or vsnprintf() return -1 instead of number of characters which would +# have been written to the final string if enough space had been available. +# # Define FREAD_READS_DIRECTORIES if your are on a system which succeeds # when attempting to read from an fopen'ed directory. #
@@ -629,6 +633,10 @@ endif ifdef NO_C99_FORMAT BASIC_CFLAGS += -DNO_C99_FORMAT endif +ifdef SNPRINTF_RETURNS_BOGUS + COMPAT_CFLAGS += -DSNPRINTF_RETURNS_BOGUS + COMPAT_OBJS += compat/snprintf.o +endif ifdef FREAD_READS_DIRECTORIES COMPAT_CFLAGS += -DFREAD_READS_DIRECTORIES COMPAT_OBJS += compat/fopen.o
diff --git a/config.mak.in b/config.mak.in
index ee6c33d..8e1cd5f 100644
--- a/config.mak.in
+++ b/config.mak.in@@ -46,3 +46,4 @@ NO_MKDTEMP=@NO_MKDTEMP@ NO_ICONV=@NO_ICONV@ OLD_ICONV=@OLD_ICONV@ NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@ +SNPRINTF_RETURNS_BOGUS=@SNPRINTF_RETURNS_BOGUS@
diff --git a/configure.ac b/configure.ac
index 85d7ef5..a3bbfa6 100644
--- a/configure.ac
+++ b/configure.ac@@ -326,6 +326,38 @@ else NO_C99_FORMAT= fi AC_SUBST(NO_C99_FORMAT) +# +# Define SNPRINTF_RETURNS_BOGUS if your are on a system which snprintf() +# or vsnprintf() return -1 instead of number of characters which would +# have been written to the final string if enough space had been available. +AC_CACHE_CHECK([whether snprintf() and/or vsnprintf() return bogus], + [ac_cv_snprintf_returns_bogus], +[ +AC_RUN_IFELSE( + [AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT + #include "stdarg.h" + + int test_vsnprintf(char *str, size_t maxsize, const char *format, ...) + { + int ret; + va_list ap; + va_start(ap, format); + ret = vsnprintf(str, maxsize, format, ap); + va_end(ap); + return ret; + }], + [[char buf[1]; + if (test_vsnprintf(buf, 1, "%s", "12345") != 5) return 1; + if (snprintf(buf, 1, "%s", "12345") != 5) return 1]])], + [ac_cv_snprintf_returns_bogus=no], + [ac_cv_snprintf_returns_bogus=yes]) +]) +if test $ac_cv_snprintf_returns_bogus = yes; then + SNPRINTF_RETURNS_BOGUS=UnfortunatelyYes +else + SNPRINTF_RETURNS_BOGUS= +fi +AC_SUBST(SNPRINTF_RETURNS_BOGUS) ## Checks for library functions.
diff --git a/git-compat-util.h b/git-compat-util.h
index 2a40703..0aa04eb 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h@@ -209,6 +209,15 @@ void *gitmemmem(const void *haystack, size_t haystacklen, extern FILE *git_fopen(const char*, const char*); #endif +#ifdef SNPRINTF_RETURNS_BOGUS +#define snprintf git_snprintf +extern int git_snprintf(char *str, size_t maxsize, + const char *format, ...); +#define vsnprintf git_vsnprintf +extern int git_vsnprintf(char *str, size_t maxsize, + const char *format, va_list ap); +#endif + #ifdef __GLIBC_PREREQ #if __GLIBC_PREREQ(2, 1) #define HAVE_STRCHRNUL
diff --git a/dev/null b/compat/snprintf.c
new file mode 100644
index 0000000..dbfc2d6
--- /dev/null
+++ b/compat/snprintf.c@@ -0,0 +1,40 @@ +#include "../git-compat-util.h" + +#undef vsnprintf +int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap) +{ + char *s; + int ret; + + ret = vsnprintf(str, maxsize, format, ap); + if (ret != -1) + return ret; + + s = NULL; + if (maxsize < 128) + maxsize = 128; + + while (ret == -1) { + maxsize *= 4; + str = realloc(s, maxsize); + if (! str) + break; + s = str; + ret = vsnprintf(str, maxsize, format, ap); + } + free(s); + return ret; +} + +int git_snprintf(char *str, size_t maxsize, const char *format, ...) +{ + va_list ap; + int ret; + + va_start(ap, format); + ret = git_vsnprintf(str, maxsize, format, ap); + va_end(ap); + + return ret; +} +
--
Michal Rokos
NextSoft s.r.o.
Vyskočilova 1/1410
140 21 Praha 4
phone: +420 267 224 311
fax: +420 267 224 307
mobile: +420 736 646 591
e-mail: michal.rokos@nextsoft.cz