[PATCH] Add compat/vsnprintf.c for systems that returns -1 on maxsize reached

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This PATCH is NOT intended to be merged (yet).

Some systems (namely HPUX) return -1 when maxsize in vsnprintf() is reached. 
So replace that broken vsnprintf() with our own that returns correct value 
upon overflow.

Could anybody give it some testing since I don't know how many broken systems 
are out there?

If anybody could think of some better define than BROKEN_VSNPRINTF, I'm all 
ears.

Linux is OK, HPUX is detected to be broken. On HPUX (11.23) test suite with 
defined BROKEN_VSNPRINTF fails in 8 *.sh testsuites, without it it fails in 
140 *.sh testsuites (out of 241).

Signed-off-by: Michal Rokos <michal.rokos@xxxxxxxxxxx>

diff --git a/Makefile b/Makefile
index ca5aad9..a1dbf1d 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,10 @@ all::
 
 # Define V=1 to have a more verbose compile.
 #
+# Define BROKEN_VSNPRINTF if your are on a system which vsnprintf() return
+# something else (typically -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.
 #
@@ -526,6 +530,7 @@ ifeq ($(uname_S),HP-UX)
 	NO_UNSETENV = YesPlease
 	NO_HSTRERROR = YesPlease
 	NO_SYS_SELECT_H = YesPlease
+	BROKEN_VSNPRINTF = UnfortunatelyYes
 endif
 ifneq (,$(findstring arm,$(uname_M)))
 	ARM_SHA1 = YesPlease
@@ -629,6 +634,10 @@ endif
 ifdef NO_C99_FORMAT
 	BASIC_CFLAGS += -DNO_C99_FORMAT
 endif
+ifdef BROKEN_VSNPRINTF
+	COMPAT_CFLAGS += -DBROKEN_VSNPRINTF
+	COMPAT_OBJS += compat/vsnprintf.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..aaa98c6 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@
+BROKEN_VSNPRINTF=@BROKEN_VSNPRINTF@
diff --git a/configure.ac b/configure.ac
index 85d7ef5..d4bb2b3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -326,6 +326,37 @@ else
 	NO_C99_FORMAT=
 fi
 AC_SUBST(NO_C99_FORMAT)
+#
+# Define BROKEN_VSNPRINTF if your are on a system which vsnprintf() return
+# something else (typically -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 vsnprintf() is broken],
+ [ac_cv_broken_vsnprintf],
+[
+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]])],
+	[ac_cv_broken_vsnprintf=no],
+	[ac_cv_broken_vsnprintf=yes])
+])
+if test $ac_cv_broken_vsnprintf = yes; then
+	BROKEN_VSNPRINTF=UnfortunatelyYes
+else
+	BROKEN_VSNPRINTF=
+fi
+AC_SUBST(BROKEN_VSNPRINTF)
 
 
 ## Checks for library functions.
diff --git a/git-compat-util.h b/git-compat-util.h
index 2a40703..5c392f8 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -209,6 +209,12 @@ void *gitmemmem(const void *haystack, size_t haystacklen,
 extern FILE *git_fopen(const char*, const char*);
 #endif
 
+#ifdef BROKEN_VSNPRINTF
+#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/vsnprintf.c
new file mode 100644
index 0000000..263e00e
--- /dev/null
+++ b/compat/vsnprintf.c
@@ -0,0 +1,20 @@
+#include "../git-compat-util.h"
+
+#undef vsnprintf
+int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap);
+{
+	int ret = vsnprintf(s, maxsize, format, ap);
+	if (ret != -1 ) return ret;
+
+	s = NULL;
+	while ( ret == -1 )
+	{
+		maxsize = (maxsize*3)/2;
+		s = realloc(s, maxsize);
+		if (! s) return -1;
+		ret = vsnprintf(s, maxsize, format, ap);
+	}
+	free(s);
+	return ret;
+}
+
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux