From: hno <> Date: Thu, 3 Jun 2004 01:19:21 +0000 (+0000) Subject: Bug #753: segfauld in memBufPrintF on architectures requiring the use of va_copy X-Git-Tag: SQUID_3_0_PRE4~1089 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=eee79a2e7b4cee23c13acd3cd237fa976449764b;p=thirdparty%2Fsquid.git Bug #753: segfauld in memBufPrintF on architectures requiring the use of va_copy to copy a va_list argument. --- diff --git a/configure.in b/configure.in index c3ab2d8068..6fdfdd0466 100644 --- a/configure.in +++ b/configure.in @@ -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 + 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 + 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 diff --git a/src/MemBuf.cc b/src/MemBuf.cc index 31fadee7c9..ba07b4b413 100644 --- a/src/MemBuf.cc +++ b/src/MemBuf.cc @@ -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 @@ -97,7 +97,19 @@ * -- 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 */