View Single Post
  #3  
Old 06-10-2009, 08:23 PM
gaeorn
Developer
 
Join Date: Apr 2009
Location: USA
Posts: 478
Default

Apparently va_lists are not preserved in (most) 64bit linux libraries after vprintf (and variations) calls. This causes segfaults under 64bit when a va_list is reused. This patch avoids reusing va_lists.

Code:
Index: common/MiscFunctions.cpp
===================================================================
--- common/MiscFunctions.cpp    (revision 3)
+++ common/MiscFunctions.cpp    (revision 4)
@@ -148,7 +148,6 @@
        int buf_len = 128;
     int chars = -1;
        va_list argptr;
-       va_start(argptr, format);
        while (chars == -1 || chars >= buf_len) {
                safe_delete_array(*ret);
                if (chars == -1)
@@ -156,9 +155,10 @@
                else
                        buf_len = chars + 1;
                *ret = new char[buf_len];
+               va_start(argptr, format);
                chars = vsnprintf(*ret, buf_len, format, argptr);
+               va_end(argptr);
        }
-       va_end(argptr);
        return chars;
 }

@@ -170,7 +170,6 @@
     int chars = -1;
        char* oldret = 0;
        va_list argptr;
-       va_start(argptr, format);
        while (chars == -1 || chars >= (sint32)(*bufsize-*strlen)) {
                if (chars == -1)
                        *bufsize += 256;
@@ -183,7 +182,9 @@
                                memcpy(*ret, oldret, *strlen);
                        safe_delete_array(oldret);
                }
+               va_start(argptr, format);
                chars = vsnprintf(&(*ret)[*strlen], (*bufsize-*strlen), format, argptr);
+               va_end(argptr);
        }
        va_end(argptr);
        *strlen += chars;
Index: common/debug.cpp
===================================================================
--- common/debug.cpp    (revision 3)
+++ common/debug.cpp    (revision 4)
@@ -144,11 +144,16 @@

        va_list argptr;
        va_start(argptr, fmt);
-    if (dofile)
+    if (dofile) {
                vfprintf( fp[id], fmt, argptr );
+               va_end(argptr);
+               va_start(argptr, fmt);
+       }
        if(logCallbackFmt[id]) {
                msgCallbackFmt p = logCallbackFmt[id];
                p(id, fmt, argptr );
+               va_end(argptr);
+               va_start(argptr, fmt);
        }
     if (pLogStatus[id] & 2) {
                if (pLogStatus[id] & 8) {
@@ -202,17 +207,21 @@
     time( &aclock );                 /* Get time in seconds */
     newtime = localtime( &aclock );  /* Convert time to struct */

+    va_list tmpargptr;
+
     if (dofile) {
 #ifndef NO_PIDLOG
                fprintf(fp[id], "[%02d.%02d. - %02d:%02d:%02d] %s", newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec, prefix);
 #else
                fprintf(fp[id], "%04i [%02d.%02d. - %02d:%02d:%02d] %s", getpid(), newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec, prefix);
 #endif
-               vfprintf( fp[id], fmt, argptr );
+               va_copy(tmpargptr, argptr);
+               vfprintf( fp[id], fmt, tmpargptr );
     }
        if(logCallbackPva[id]) {
                msgCallbackPva p = logCallbackPva[id];
-               p(id, prefix, fmt, argptr );
+               va_copy(tmpargptr, argptr);
+               p(id, prefix, fmt, tmpargptr );
        }
     if (pLogStatus[id] & 2) {
                if (pLogStatus[id] & 8) {
@@ -295,8 +304,11 @@
 bool EQEMuLog::writeNTS(LogIDs id, bool dofile, const char *fmt, ...) {
        va_list argptr;
        va_start(argptr, fmt);
-       if (dofile)
+       if (dofile) {
                vfprintf( fp[id], fmt, argptr );
+               va_end(argptr);
+               va_start(argptr, fmt);
+       }
     if (pLogStatus[id] & 2) {
                if (pLogStatus[id] & 8)
                        vfprintf( stderr, fmt, argptr );
Reply With Quote