]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Bug #753: segfauld in memBufPrintF on architectures requiring the use of va_copy
authorhno <>
Thu, 3 Jun 2004 01:19:21 +0000 (01:19 +0000)
committerhno <>
Thu, 3 Jun 2004 01:19:21 +0000 (01:19 +0000)
to copy a va_list argument.

configure.in
src/MemBuf.cc

index c3ab2d80680fef601df7176e0d93728c25873b2e..6fdfdd04664587f1e8fead33c1f13ec1ed7af976 100644 (file)
@@ -3,7 +3,7 @@ dnl  Configuration input file for Squid
 dnl
 dnl  Duane Wessels, wessels@nlanr.net, February 1996 (autoconf v2.9)
 dnl
-dnl  $Id: configure.in,v 1.354 2004/04/08 01:29:05 hno Exp $
+dnl  $Id: configure.in,v 1.355 2004/06/02 19:19:21 hno Exp $
 dnl
 dnl
 dnl
@@ -13,7 +13,7 @@ AC_CONFIG_SRCDIR([src/main.cc])
 AC_CONFIG_AUX_DIR(cfgaux)
 AM_INIT_AUTOMAKE(squid, 3.0-PRE3-CVS)
 AM_CONFIG_HEADER(include/autoconf.h)
-AC_REVISION($Revision: 1.354 $)dnl
+AC_REVISION($Revision: 1.355 $)dnl
 AC_PREFIX_DEFAULT(/usr/local/squid)
 AM_MAINTAINER_MODE
 
@@ -2034,6 +2034,54 @@ AM_CONDITIONAL(NEED_OWN_SNPRINTF, false)
 if test "$ac_cv_func_snprintf" = "no" || test "$ac_cv_func_vsnprintf" = "no" ; then
   AM_CONDITIONAL(NEED_OWN_SNPRINTF, true)
 fi
+
+dnl
+dnl Test for va_copy
+dnl
+AC_CACHE_CHECK(if va_copy is implemented, ac_cv_func_va_copy,
+  AC_TRY_RUN([
+      #include <stdarg.h>
+      void f (int i, ...) {
+         va_list args1, args2;
+         va_start (args1, i);
+         va_copy (args2, args1);
+         if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
+            exit (1);
+         va_end (args1); va_end (args2);
+      }
+      int main() {
+         f (0, 42);
+         return 0;
+      }
+      ],ac_cv_func_va_copy="yes",ac_cv_func_va_copy="no")
+)
+if test "$ac_cv_func_va_copy" = "yes" ; then
+  AC_DEFINE(HAVE_VA_COPY)
+fi
+
+dnl
+dnl Some systems support __va_copy
+dnl
+AC_CACHE_CHECK(if __va_copy is implemented, ac_cv_func___va_copy,
+  AC_TRY_RUN([
+      #include <stdarg.h>
+      void f (int i, ...) {
+         va_list args1, args2;
+         va_start (args1, i);
+         __va_copy (args2, args1);
+         if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
+            exit (1);
+         va_end (args1); va_end (args2);
+      }
+      int main() {
+         f (0, 42);
+         return 0;
+      }
+      ],ac_cv_func___va_copy="yes",ac_cv_func___va_copy="no")
+)
+if test "$ac_cv_func___va_copy" = "yes" ; then
+  AC_DEFINE(HAVE___VA_COPY)
+fi
   
 dnl IP-Filter support requires ipf header files. These aren't
 dnl installed by default, so we need to check for them
index 31fadee7c91527218ef4bd43c1412b6c43b84470..ba07b4b4136a5b412df124257cd9e2fff5953ba1 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: MemBuf.cc,v 1.34 2003/02/21 22:50:05 robertc Exp $
+ * $Id: MemBuf.cc,v 1.35 2004/06/02 19:19:21 hno Exp $
  *
  * DEBUG: section 59    auto-growing Memory Buffer with printf
  * AUTHOR: Alex Rousskov
  * -- memBufClean(&buf);
  * }
  */
+/* if you have configure you can use this */
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
 
+#ifdef VA_COPY
+#undef VA_COPY
+#endif
+#if defined HAVE_VA_COPY
+#define VA_COPY va_copy
+#elif defined HAVE___VA_COPY
+#define VA_COPY __va_copy
+#endif
 
 #include "squid.h"
 
@@ -235,6 +247,10 @@ va_dcl
 /* vprintf for other printf()'s to use; calls vsnprintf, extends buf if needed */
 void
 memBufVPrintf(MemBuf * mb, const char *fmt, va_list vargs) {
+#ifdef VA_COPY
+    va_list ap;
+#endif
+
     int sz = 0;
     assert(mb && fmt);
     assert(mb->buf);
@@ -244,7 +260,18 @@ memBufVPrintf(MemBuf * mb, const char *fmt, va_list vargs) {
     while (mb->capacity <= mb->max_capacity) {
         mb_size_t free_space = mb->capacity - mb->size;
         /* put as much as we can */
+
+#ifdef VA_COPY
+        /* Fix of bug 753r. The value of vargs is undefined
+         * after vsnprintf() returns. Make a copy of vargs
+         * incase we loop around and call vsnprintf() again.
+         */
+        VA_COPY(ap,vargs);
+        sz = vsnprintf(mb->buf + mb->size, free_space, fmt, ap);
+#else /* VA_COPY */
+
         sz = vsnprintf(mb->buf + mb->size, free_space, fmt, vargs);
+#endif /*VA_COPY*/
         /* check for possible overflow */
         /* snprintf on Linuz returns -1 on overflows */
         /* snprintf on FreeBSD returns at least free_space on overflows */
@@ -255,6 +282,7 @@ memBufVPrintf(MemBuf * mb, const char *fmt, va_list vargs) {
             break;
     }
 
+    va_end(ap);
     mb->size += sz;
     /* on Linux and FreeBSD, '\0' is not counted in return value */
     /* on XXX it might be counted */