Hi,

Wget-1.7 makes invalid use of stdarg/vsnprintf, which results in wget
dumping core on GNU/Linux powerpc:

    23:32:36 appel ~/usr/src/wget-1.7/src$ ./wget 
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 
    --23:32:37--  
http://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/
               => `index.html'
    Connecting to 
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:80... 
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: 
Host not found.
    23:32:37 appel ~/usr/src/wget-1.7/src$ ./wget 
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab
    Segmentation fault (core dumped)


The function log.c:logvprintf () calls vsnprintf without restarting
the stdargs, 

printf(3)
       The  functions  vprintf, vfprintf, vsprintf, vsnprintf are
       equivalent to  the  functions  printf,  fprintf,  sprintf,
       snprintf, respectively, except that they are called with a
       va_list instead of a variable number of  arguments.  These
       functions  do not call the va_end macro. Consequently, the
       value of ap is undefined after the call.  The  application
       should call va_end(ap) itself afterwards.

and on powerpc, args is more undefined than on i386 :-)

Greetings,
Jan.


diff -urpN --exclude=*~ ../wget-1.7/src/ChangeLog ./src/ChangeLog
--- ../wget-1.7/src/ChangeLog   Mon Jun  4 12:45:20 2001
+++ ./src/ChangeLog     Thu Jul 19 00:08:36 2001
@@ -1,3 +1,15 @@
+2001-07-19  Jan Nieuwenhuizen  <[EMAIL PROTECTED]>
+
+       * log.c (logvprintf): [WGET_USE_STDARG] Rename to logprint, take
+       variable arg list of logprint.
+       
+       Bugfix: call va_start before each call of vsnprintf.
+       
+       (logprintf): [WGET_USE_STDARG] Remove.
+       (debug_logprintf): [WGET_USE_STDARG] Remove.
+
+       * wget.h (debug_logprintf): [HAVE_STDARG_H]Define as macro
+
 2001-06-04  Hrvoje Niksic  <[EMAIL PROTECTED]>
 
        * version.c: Wget 1.7 is released.
diff -urpN --exclude=*~ ../wget-1.7/src/log.c ./src/log.c
--- ../wget-1.7/src/log.c       Sun May 27 21:35:05 2001
+++ ./src/log.c Thu Jul 19 00:05:23 2001
@@ -277,9 +277,18 @@ logputs (enum log_options o, const char 
 /* Print a message to the log.  A copy of message will be saved to
    saved_log, for later reusal by log_dump().  */
 
+#ifdef WGET_USE_STDARG
+void
+logprintf (enum log_options o, const char *fmt, ...)
+#else
 static void
 logvprintf (enum log_options o, const char *fmt, va_list args)
+#endif     
 {
+#ifdef WGET_USE_STDARG
+  va_list args;
+#endif
+  
   CHECK_VERBOSE (o);
   CANONICALIZE_LOGFP_OR_RETURN;
 
@@ -292,6 +301,9 @@ logvprintf (enum log_options o, const ch
     {
       /* In the simple case just call vfprintf(), to avoid needless
          allocation and games with vsnprintf(). */
+#ifdef WGET_USE_STDARG
+      va_start (args, fmt);
+#endif
       vfprintf (logfp, fmt, args);
     }
   else
@@ -303,6 +315,8 @@ logvprintf (enum log_options o, const ch
 
       while (1)
        {
+         int numwritten;
+         
          /* The GNU coding standards advise not to rely on the return
              value of sprintf().  However, vsnprintf() is a relatively
              new function missing from legacy systems.  Therefore it's
@@ -310,8 +324,11 @@ logvprintf (enum log_options o, const ch
              the systems where vsnprintf() is not available, we use
              the implementation from snprintf.c which does return the
              correct value.  */
-         int numwritten = vsnprintf (write_ptr, available_size, fmt, args);
-
+#ifdef WGET_USE_STDARG
+         va_start (args, fmt);
+#endif   
+         numwritten = vsnprintf (write_ptr, available_size, fmt, args);
+         
          /* vsnprintf() will not step over the limit given by
              available_size.  If it fails, it will return either -1
              (POSIX?) or the number of characters that *would have*
@@ -350,6 +367,10 @@ logvprintf (enum log_options o, const ch
     }
   if (!opt.no_flush)
     fflush (logfp);
+  
+#ifdef WGET_USE_STDARG
+  va_end (args);
+#endif   
 }
 
 /* Flush LOGFP.  */
@@ -363,28 +384,15 @@ logflush (void)
 /* Portability with pre-ANSI compilers makes these two functions look
    like @#%#@$@#$.  */
 
-#ifdef WGET_USE_STDARG
-void
-logprintf (enum log_options o, const char *fmt, ...)
-#else  /* not WGET_USE_STDARG */
+#ifndef WGET_USE_STDARG
 void
 logprintf (va_alist)
      va_dcl
-#endif /* not WGET_USE_STDARG */
 {
   va_list args;
-#ifndef WGET_USE_STDARG
-  enum log_options o;
-  const char *fmt;
-#endif
-
-#ifdef WGET_USE_STDARG
-  va_start (args, fmt);
-#else
   va_start (args);
   o = va_arg (args, enum log_options);
   fmt = va_arg (args, char *);
-#endif
   logvprintf (o, fmt, args);
   va_end (args);
 }
@@ -392,33 +400,23 @@ logprintf (va_alist)
 #ifdef DEBUG
 /* The same as logprintf(), but does anything only if opt.debug is
    non-zero.  */
-#ifdef WGET_USE_STDARG
-void
-debug_logprintf (const char *fmt, ...)
-#else  /* not WGET_USE_STDARG */
 void
 debug_logprintf (va_alist)
      va_dcl
-#endif /* not WGET_USE_STDARG */
 {
   if (opt.debug)
     {
       va_list args;
-#ifndef WGET_USE_STDARG
       const char *fmt;
-#endif
-
-#ifdef WGET_USE_STDARG
-      va_start (args, fmt);
-#else
       va_start (args);
       fmt = va_arg (args, char *);
-#endif
       logvprintf (LOG_ALWAYS, fmt, args);
       va_end (args);
     }
 }
 #endif /* DEBUG */
+#endif /* not WGET_USE_STDARG */
+
 
 /* Open FILE and set up a logging stream.  If FILE cannot be opened,
    exit with status of 1.  */
diff -urpN --exclude=*~ ../wget-1.7/src/wget.h ./src/wget.h
--- ../wget-1.7/src/wget.h      Sun May 27 21:35:15 2001
+++ ./src/wget.h        Thu Jul 19 00:02:20 2001
@@ -92,7 +92,7 @@ enum log_options { LOG_VERBOSE, LOG_NOTQ
 #ifdef HAVE_STDARG_H
 void logprintf PARAMS ((enum log_options, const char *, ...))
      GCC_FORMAT_ATTR (2, 3);
-void debug_logprintf PARAMS ((const char *, ...)) GCC_FORMAT_ATTR (1, 2);
+#define debug_logprintf(s, args...) logprintf (LOG_ALWAYS, s, ##args)
 #else  /* not HAVE_STDARG_H */
 void logprintf ();
 void debug_logprintf ();


-- 
Jan Nieuwenhuizen <[EMAIL PROTECTED]> | GNU LilyPond - The music typesetter
http://www.xs4all.nl/~jantien       | http://www.lilypond.org

Reply via email to