2004-03-01 David Zeuthen <david@fubar.dk>
authorDavid Zeuthen <davidz@redhat.com>
Fri, 5 Mar 2004 14:05:33 +0000 (14:05 +0000)
committerDavid Zeuthen <davidz@redhat.com>
Fri, 5 Mar 2004 14:05:33 +0000 (14:05 +0000)
* dbus/dbus-string.c (_dbus_string_append_printf_valist): Fix a
bug where args were used twice. This bug resulted in a segfault
on a Debian/PPC system when starting the messagebus daemon. Include
dbus-sysdeps.h for DBUS_VA_COPY

* dbus/dbus-sysdeps.h: Define DBUS_VA_COPY if neccessary. From GLib

* configure.in: Check for va_copy; define DBUS_VA_COPY to the
appropriate va_copy implementation. From GLib

ChangeLog
configure.in
dbus/dbus-string.c
dbus/dbus-sysdeps.h

index af872a9..f099f0b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2004-03-01  David Zeuthen  <david@fubar.dk>
+
+       * dbus/dbus-string.c (_dbus_string_append_printf_valist): Fix a
+       bug where args were used twice. This bug resulted in a segfault
+       on a Debian/PPC system when starting the messagebus daemon. Include
+       dbus-sysdeps.h for DBUS_VA_COPY
+
+       * dbus/dbus-sysdeps.h: Define DBUS_VA_COPY if neccessary. From GLib
+
+       * configure.in: Check for va_copy; define DBUS_VA_COPY to the
+       appropriate va_copy implementation. From GLib
+       
 2004-02-24  Joe Shaw  <joe@ximian.com>
 
        * bus/services.c (bus_registry_acquire_service): We need to pass
index 5d08f26..2e32315 100644 (file)
@@ -293,6 +293,82 @@ AC_SUBST(DBUS_HAVE_INT64)
 ## byte order
 AC_C_BIGENDIAN
 
+
+dnl **********************************
+dnl *** va_copy checks (from GLib) ***
+dnl **********************************
+dnl we currently check for all three va_copy possibilities, so we get
+dnl all results in config.log for bug reports.
+AC_CACHE_CHECK([for an implementation of va_copy()],dbus_cv_va_copy,[
+       AC_LINK_IFELSE([#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;
+       }],
+       [dbus_cv_va_copy=yes],
+       [dbus_cv_va_copy=no])
+])
+AC_CACHE_CHECK([for an implementation of __va_copy()],dbus_cv___va_copy,[
+       AC_LINK_IFELSE([#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;
+       }],
+       [dbus_cv___va_copy=yes],
+       [dbus_cv___va_copy=no])
+])
+
+if test "x$dbus_cv_va_copy" = "xyes"; then
+  dbus_va_copy_func=va_copy
+else if test "x$dbus_cv___va_copy" = "xyes"; then
+  dbus_va_copy_func=__va_copy
+fi
+fi
+
+if test -n "$dbus_va_copy_func"; then
+  AC_DEFINE_UNQUOTED(DBUS_VA_COPY,$dbus_va_copy_func,[A 'va_copy' style function])
+fi
+
+AC_CACHE_CHECK([whether va_lists can be copied by value],dbus_cv_va_val_copy,[
+       AC_TRY_RUN([#include <stdarg.h>
+       void f (int i, ...) {
+       va_list args1, args2;
+       va_start (args1, i);
+       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;
+       }],
+       [dbus_cv_va_val_copy=yes],
+       [dbus_cv_va_val_copy=no],
+       [dbus_cv_va_val_copy=yes])
+])
+
+if test "x$dbus_cv_va_val_copy" = "xno"; then
+  AC_DEFINE(DBUS_VA_COPY_AS_ARRAY,1, ['va_lists' cannot be copies as values])
+fi
+
+
 #### Atomic integers (checks by Sebastian Wilhelmi for GLib)
 AC_MSG_CHECKING([whether to use inline assembler routines for atomic integers])
 have_atomic_inc=no
index f78d01c..6a83398 100644 (file)
@@ -31,6 +31,8 @@
 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
 #include "dbus-string-private.h"
 #include "dbus-protocol.h"
+/* for DBUS_VA_COPY */
+#include "dbus-sysdeps.h"
 
 /**
  * @defgroup DBusString string class
@@ -1013,16 +1015,26 @@ _dbus_string_append_printf_valist  (DBusString        *str,
 {
   int len;
   char c;
+  va_list args_copy;
+
   DBUS_STRING_PREAMBLE (str);
-  
+
+  DBUS_VA_COPY (args_copy, args);
+
   /* Measure the message length without terminating nul */
   len = vsnprintf (&c, 1, format, args);
 
   if (!_dbus_string_lengthen (str, len))
-    return FALSE;
-
+    {
+      /* don't leak the copy */
+      va_end (args_copy);
+      return FALSE;
+    }
+  
   vsprintf (real->str + (real->len - len),
-            format, args);
+            format, args_copy);
+
+  va_end (args_copy);
 
   return TRUE;
 }
index da71f99..5febc6e 100644 (file)
@@ -306,6 +306,20 @@ void _dbus_set_signal_handler (int               sig,
                                DBusSignalHandler handler);
 
 
+/* Define DBUS_VA_COPY() to do the right thing for copying va_list variables. 
+ * config.h may have already defined DBUS_VA_COPY as va_copy or __va_copy. 
+ */
+#if !defined (DBUS_VA_COPY)
+#  if defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32))
+#    define DBUS_VA_COPY(ap1, ap2)   (*(ap1) = *(ap2))
+#  elif defined (DBUS_VA_COPY_AS_ARRAY)
+#    define DBUS_VA_COPY(ap1, ap2)   memcpy ((ap1), (ap2), sizeof (va_list))
+#  else /* va_list is a pointer */
+#    define DBUS_VA_COPY(ap1, ap2)   ((ap1) = (ap2))
+#  endif /* va_list is a pointer */
+#endif /* !DBUS_VA_COPY */
+
+
 DBUS_END_DECLS;
 
 #endif /* DBUS_SYSDEPS_H */