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