[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Bug-gnulib] proposed vasnprintf patches for address arithmetic and stac
From: |
Paul Eggert |
Subject: |
[Bug-gnulib] proposed vasnprintf patches for address arithmetic and stack overflow |
Date: |
15 Nov 2003 00:07:18 -0800 |
User-agent: |
Gnus/5.09 (Gnus v5.9.0) Emacs/21.3 |
Here are some proposed patches for the vasnprintf module of gnulib.
I don't use this code myself, so I haven't tested it other than
by compiling it.
2003-11-14 Paul Eggert <address@hidden>
Fix some problems with address arithmetic overflow. Some of
them are more feasible than others (e.g., a print width exceeding
INT_MAX is more feasible than having more than UINT_MAX args), but
it's easy enough to fix them all while we're in the neighborhood.
I also fixed a potential alloca overflow while I was in the
neighborhood.
* printf-args.h (arguments): Use size_t for sizes.
* printf-args.c (printf_fetchargs): Likewise.
* printf-parse.h (char_directive, char_directives): Likewise.
* printf-parse.c (printf_parse, REGISTER_ARG): Likewise.
* vasnprintf.c (vasnprintf): Likewise.
* printf-parse.c: Include "xsize.h".
* printf-parse.c (printf_parse, REGISTER_ARG):
Check for arithmetic overflow in size calculations.
* vasnprintf.c (vasnprintf): Likewise.
* vasnprintf.c (ALLOCA_LIMIT): New macro.
(freea): Remove. All uses removed.
(alloca) [!HAVE_ALLOCA]: Define to NULL, not to malloc,
to let the reader know that it will never be invoked.
(vasnprintf, CLEANUP): Record address of any storage that
needs to be freed in a local variable needs_freeing.
Initialize 'result' and 'allocated' early, so that CLEANUP
can rely on their contents. Use alloca only for buffers smaller
than ALLOCA_LIMIT. Establish a new out_of_memory label to
remove duplicate code for freeing storage.
(vasnprintf): Don't compute (arg < 0 ? -arg : arg), as this
mishandles the case when arg == INT_MIN && INT_MIN < -INT_MAX
&& INT_MAX < SIZE_MAX / 2.
Index: lib/printf-args.h
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/printf-args.h,v
retrieving revision 1.2
diff -p -u -r1.2 printf-args.h
--- lib/printf-args.h 14 Jul 2003 22:44:04 -0000 1.2
+++ lib/printf-args.h 15 Nov 2003 07:42:55 -0000
@@ -116,7 +116,7 @@ argument;
typedef struct
{
- unsigned int count;
+ size_t count;
argument *arg;
}
arguments;
Index: lib/printf-args.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/printf-args.c,v
retrieving revision 1.2
diff -p -u -r1.2 printf-args.c
--- lib/printf-args.c 14 Jul 2003 22:44:04 -0000 1.2
+++ lib/printf-args.c 15 Nov 2003 07:42:55 -0000
@@ -28,7 +28,7 @@ STATIC
int
printf_fetchargs (va_list args, arguments *a)
{
- unsigned int i;
+ size_t i;
argument *ap;
for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++)
Index: lib/printf-parse.h
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/printf-parse.h,v
retrieving revision 1.2
diff -p -u -r1.2 printf-parse.h
--- lib/printf-parse.h 14 Jul 2003 22:44:04 -0000 1.2
+++ lib/printf-parse.h 15 Nov 2003 07:42:56 -0000
@@ -37,22 +37,22 @@ typedef struct
int flags;
const char* width_start;
const char* width_end;
- int width_arg_index;
+ size_t width_arg_index;
const char* precision_start;
const char* precision_end;
- int precision_arg_index;
+ size_t precision_arg_index;
char conversion; /* d i o u x X f e E g G c s p n U % but not C S */
- int arg_index;
+ size_t arg_index;
}
char_directive;
/* A parsed format string. */
typedef struct
{
- unsigned int count;
+ size_t count;
char_directive *dir;
- unsigned int max_width_length;
- unsigned int max_precision_length;
+ size_t max_width_length;
+ size_t max_precision_length;
}
char_directives;
Index: lib/printf-parse.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/printf-parse.c,v
retrieving revision 1.2
diff -p -u -r1.2 printf-parse.c
--- lib/printf-parse.c 14 Jul 2003 22:44:04 -0000 1.2
+++ lib/printf-parse.c 15 Nov 2003 07:42:56 -0000
@@ -25,6 +25,8 @@
/* Get size_t, NULL. */
#include <stddef.h>
+#include "xsize.h"
+
/* Get intmax_t. */
#if HAVE_STDINT_H_WITH_UINTMAX
# include <stdint.h>
@@ -43,11 +45,11 @@ int
printf_parse (const char *format, char_directives *d, arguments *a)
{
const char *cp = format; /* pointer into format */
- int arg_posn = 0; /* number of regular arguments consumed */
- unsigned int d_allocated; /* allocated elements of d->dir */
- unsigned int a_allocated; /* allocated elements of a->arg */
- unsigned int max_width_length = 0;
- unsigned int max_precision_length = 0;
+ size_t arg_posn = 0; /* number of regular arguments consumed */
+ size_t d_allocated; /* allocated elements of d->dir */
+ size_t a_allocated; /* allocated elements of a->arg */
+ size_t max_width_length = 0;
+ size_t max_precision_length = 0;
d->count = 0;
d_allocated = 1;
@@ -62,16 +64,18 @@ printf_parse (const char *format, char_d
#define REGISTER_ARG(_index_,_type_) \
{ \
- unsigned int n = (_index_);
\
+ size_t n = (_index_); \
if (n >= a_allocated) \
{
\
+ size_t size; \
argument *memory; \
a_allocated = 2 * a_allocated; \
if (a_allocated <= n) \
a_allocated = n + 1; \
- memory = (a->arg \
- ? realloc (a->arg, a_allocated * sizeof (argument)) \
- : malloc (a_allocated * sizeof (argument))); \
+ size = xtimes (a_allocated, sizeof *memory); \
+ if (size_overflow_p (size)) \
+ goto error; \
+ memory = a->arg ? realloc (a->arg, size) : malloc (size); \
if (memory == NULL) \
/* Out of memory. */ \
goto error; \
@@ -91,7 +95,7 @@ printf_parse (const char *format, char_d
char c = *cp++;
if (c == '%')
{
- int arg_index = -1;
+ size_t arg_index = SIZE_MAX;
char_directive *dp = &d->dir[d->count];/* pointer to next directive */
/* Initialize the next directive. */
@@ -99,11 +103,11 @@ printf_parse (const char *format, char_d
dp->flags = 0;
dp->width_start = NULL;
dp->width_end = NULL;
- dp->width_arg_index = -1;
+ dp->width_arg_index = SIZE_MAX;
dp->precision_start = NULL;
dp->precision_end = NULL;
- dp->precision_arg_index = -1;
- dp->arg_index = -1;
+ dp->precision_arg_index = SIZE_MAX;
+ dp->arg_index = SIZE_MAX;
/* Test for positional argument. */
if (*cp >= '0' && *cp <= '9')
@@ -114,7 +118,7 @@ printf_parse (const char *format, char_d
;
if (*np == '$')
{
- unsigned int n = 0;
+ size_t n = 0;
for (np = cp; *np >= '0' && *np <= '9'; np++)
n = 10 * n + (*np - '0');
@@ -181,7 +185,7 @@ printf_parse (const char *format, char_d
;
if (*np == '$')
{
- unsigned int n = 0;
+ size_t n = 0;
for (np = cp; *np >= '0' && *np <= '9'; np++)
n = 10 * n + (*np - '0');
@@ -192,13 +196,13 @@ printf_parse (const char *format, char_d
cp = np + 1;
}
}
- if (dp->width_arg_index < 0)
+ if (dp->width_arg_index == SIZE_MAX)
dp->width_arg_index = arg_posn++;
REGISTER_ARG (dp->width_arg_index, TYPE_INT);
}
else if (*cp >= '0' && *cp <= '9')
{
- unsigned int width_length;
+ size_t width_length;
dp->width_start = cp;
for (; *cp >= '0' && *cp <= '9'; cp++)
@@ -230,7 +234,7 @@ printf_parse (const char *format, char_d
;
if (*np == '$')
{
- unsigned int n = 0;
+ size_t n = 0;
for (np = cp; *np >= '0' && *np <= '9'; np++)
n = 10 * n + (*np - '0');
@@ -241,13 +245,13 @@ printf_parse (const char *format, char_d
cp = np + 1;
}
}
- if (dp->precision_arg_index < 0)
+ if (dp->precision_arg_index == SIZE_MAX)
dp->precision_arg_index = arg_posn++;
REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
}
else
{
- unsigned int precision_length;
+ size_t precision_length;
dp->precision_start = cp - 1;
for (; *cp >= '0' && *cp <= '9'; cp++)
@@ -439,7 +443,7 @@ printf_parse (const char *format, char_d
if (type != TYPE_NONE)
{
dp->arg_index = arg_index;
- if (dp->arg_index < 0)
+ if (dp->arg_index == SIZE_MAX)
dp->arg_index = arg_posn++;
REGISTER_ARG (dp->arg_index, type);
}
@@ -450,10 +454,14 @@ printf_parse (const char *format, char_d
d->count++;
if (d->count >= d_allocated)
{
+ size_t size;
char_directive *memory;
d_allocated = 2 * d_allocated;
- memory = realloc (d->dir, d_allocated * sizeof (char_directive));
+ size = xtimes (d_allocated, sizeof *memory);
+ if (size_overflow_p (size))
+ goto error;
+ memory = realloc (d->dir, size);
if (memory == NULL)
/* Out of memory. */
goto error;
Index: lib/vasnprintf.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/vasnprintf.c,v
retrieving revision 1.8
diff -p -u -r1.8 vasnprintf.c
--- lib/vasnprintf.c 20 Oct 2003 10:51:59 -0000 1.8
+++ lib/vasnprintf.c 15 Nov 2003 07:42:56 -0000
@@ -37,14 +37,14 @@
#include <limits.h> /* CHAR_BIT */
#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
#include "printf-parse.h"
+#include "xsize.h"
-/* For those losing systems which don't have 'alloca' we have to add
- some additional code emulating it. */
#ifdef HAVE_ALLOCA
-# define freea(p) /* nothing */
+# define ALLOCA_LIMIT 8000
#else
-# define alloca(n) malloc (n)
-# define freea(p) free (p)
+# define ALLOCA_LIMIT 0
+# undef alloca
+# define alloca(n) NULL
#endif
#ifdef HAVE_WCHAR_T
@@ -70,6 +70,7 @@ vasnprintf (char *resultbuf, size_t *len
{
char_directives d;
arguments a;
+ void *needs_freeing = NULL;
if (printf_parse (format, &d, &a) < 0)
{
@@ -78,6 +79,8 @@ vasnprintf (char *resultbuf, size_t *len
}
#define CLEANUP() \
+ if (needs_freeing) \
+ free (needs_freeing); \
free (d.dir);
\
if (a.arg) \
free (a.arg);
@@ -90,26 +93,27 @@ vasnprintf (char *resultbuf, size_t *len
}
{
- char *buf =
- (char *) alloca (7 + d.max_width_length + d.max_precision_length + 6);
+ size_t bufsize = xsum3 (7 + 6, d.max_width_length, d.max_precision_length);
+ char *buf;
const char *cp;
- unsigned int i;
+ size_t i;
char_directive *dp;
/* Output string accumulator. */
- char *result;
- size_t allocated;
+ char *result = NULL;
+ size_t allocated = 0;
size_t length;
+ if (bufsize < ALLOCA_LIMIT)
+ buf = (char *) alloca (bufsize);
+ else if (size_overflow_p (bufsize)
+ || ! (buf = needs_freeing = malloc (bufsize)))
+ goto out_of_memory;
+
if (resultbuf != NULL)
{
result = resultbuf;
allocated = *lengthp;
}
- else
- {
- result = NULL;
- allocated = 0;
- }
length = 0;
/* Invariants:
result is either == resultbuf or == NULL or malloc-allocated.
@@ -129,14 +133,7 @@ vasnprintf (char *resultbuf, size_t *len
memory = (char *) realloc (result, allocated); \
\
if (memory == NULL) \
- { \
- if (!(result == resultbuf || result == NULL)) \
- free (result); \
- freea (buf); \
- CLEANUP (); \
- errno = ENOMEM; \
- return NULL; \
- } \
+ goto out_of_memory; \
if (result == resultbuf && length > 0) \
memcpy (memory, result, length); \
result = memory; \
@@ -147,8 +144,11 @@ vasnprintf (char *resultbuf, size_t *len
if (cp != dp->dir_start)
{
size_t n = dp->dir_start - cp;
+ size_t needed = xsum (length, n);
- ENSURE_ALLOCATION (length + n);
+ if (size_overflow_p (needed))
+ goto out_of_memory;
+ ENSURE_ALLOCATION (needed);
memcpy (result + length, cp, n);
length += n;
}
@@ -158,7 +158,7 @@ vasnprintf (char *resultbuf, size_t *len
/* Execute a single directive. */
if (dp->conversion == '%')
{
- if (!(dp->arg_index < 0))
+ if (!(dp->arg_index == SIZE_MAX))
abort ();
ENSURE_ALLOCATION (length + 1);
result[length] = '%';
@@ -166,7 +166,7 @@ vasnprintf (char *resultbuf, size_t *len
}
else
{
- if (!(dp->arg_index >= 0))
+ if (!(dp->arg_index != SIZE_MAX))
abort ();
if (dp->conversion == 'n')
@@ -201,27 +201,29 @@ vasnprintf (char *resultbuf, size_t *len
unsigned int prefix_count;
int prefixes[2];
#if !HAVE_SNPRINTF
- unsigned int tmp_length;
+ size_t tmp_length;
char tmpbuf[700];
char *tmp;
/* Allocate a temporary buffer of sufficient size for calling
sprintf. */
{
- unsigned int width;
- unsigned int precision;
+ size_t width;
+ size_t precision;
width = 0;
if (dp->width_start != dp->width_end)
{
- if (dp->width_arg_index >= 0)
+ if (dp->width_arg_index != SIZE_MAX)
{
int arg;
if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
abort ();
arg = a.arg[dp->width_arg_index].a.a_int;
- width = (arg < 0 ? -arg : arg);
+ width = arg;
+ if (arg < 0)
+ width = -width;
}
else
{
@@ -236,7 +238,7 @@ vasnprintf (char *resultbuf, size_t *len
precision = 6;
if (dp->precision_start != dp->precision_end)
{
- if (dp->precision_arg_index >= 0)
+ if (dp->precision_arg_index != SIZE_MAX)
{
int arg;
@@ -263,28 +265,28 @@ vasnprintf (char *resultbuf, size_t *len
# ifdef HAVE_LONG_LONG
if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
tmp_length =
- (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
- * 0.30103 /* binary -> decimal */
- * 2 /* estimate for FLAG_GROUP */
- )
+ (size_t) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ 1 /* turn floor into ceil */
+ 1; /* account for leading sign */
else
# endif
if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
tmp_length =
- (unsigned int) (sizeof (unsigned long) * CHAR_BIT
- * 0.30103 /* binary -> decimal */
- * 2 /* estimate for FLAG_GROUP */
- )
+ (size_t) (sizeof (unsigned long) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ 1 /* turn floor into ceil */
+ 1; /* account for leading sign */
else
tmp_length =
- (unsigned int) (sizeof (unsigned int) * CHAR_BIT
- * 0.30103 /* binary -> decimal */
- * 2 /* estimate for FLAG_GROUP */
- )
+ (size_t) (sizeof (unsigned int) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ 1 /* turn floor into ceil */
+ 1; /* account for leading sign */
break;
@@ -293,25 +295,25 @@ vasnprintf (char *resultbuf, size_t *len
# ifdef HAVE_LONG_LONG
if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
tmp_length =
- (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
- * 0.333334 /* binary -> octal */
- )
+ (size_t) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ 1 /* turn floor into ceil */
+ 1; /* account for leading sign */
else
# endif
if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
tmp_length =
- (unsigned int) (sizeof (unsigned long) * CHAR_BIT
- * 0.333334 /* binary -> octal */
- )
+ (size_t) (sizeof (unsigned long) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ 1 /* turn floor into ceil */
+ 1; /* account for leading sign */
else
tmp_length =
- (unsigned int) (sizeof (unsigned int) * CHAR_BIT
- * 0.333334 /* binary -> octal */
- )
+ (size_t) (sizeof (unsigned int) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ 1 /* turn floor into ceil */
+ 1; /* account for leading sign */
break;
@@ -320,25 +322,25 @@ vasnprintf (char *resultbuf, size_t *len
# ifdef HAVE_LONG_LONG
if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
tmp_length =
- (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
- * 0.25 /* binary -> hexadecimal */
- )
+ (size_t) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ 1 /* turn floor into ceil */
+ 2; /* account for leading sign or alternate form */
else
# endif
if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
tmp_length =
- (unsigned int) (sizeof (unsigned long) * CHAR_BIT
- * 0.25 /* binary -> hexadecimal */
- )
+ (size_t) (sizeof (unsigned long) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ 1 /* turn floor into ceil */
+ 2; /* account for leading sign or alternate form */
else
tmp_length =
- (unsigned int) (sizeof (unsigned int) * CHAR_BIT
- * 0.25 /* binary -> hexadecimal */
- )
+ (size_t) (sizeof (unsigned int) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ 1 /* turn floor into ceil */
+ 2; /* account for leading sign or alternate form */
break;
@@ -347,20 +349,20 @@ vasnprintf (char *resultbuf, size_t *len
# ifdef HAVE_LONG_DOUBLE
if (type == TYPE_LONGDOUBLE)
tmp_length =
- (unsigned int) (LDBL_MAX_EXP
- * 0.30103 /* binary -> decimal */
- * 2 /* estimate for FLAG_GROUP */
- )
+ (size_t) (LDBL_MAX_EXP
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ 1 /* turn floor into ceil */
+ precision
+ 10; /* sign, decimal point etc. */
else
# endif
tmp_length =
- (unsigned int) (DBL_MAX_EXP
- * 0.30103 /* binary -> decimal */
- * 2 /* estimate for FLAG_GROUP */
- )
+ (size_t) (DBL_MAX_EXP
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ 1 /* turn floor into ceil */
+ precision
+ 10; /* sign, decimal point etc. */
@@ -395,9 +397,9 @@ vasnprintf (char *resultbuf, size_t *len
case 'p':
tmp_length =
- (unsigned int) (sizeof (void *) * CHAR_BIT
- * 0.25 /* binary -> hexadecimal */
- )
+ (size_t) (sizeof (void *) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ 1 /* turn floor into ceil */
+ 2; /* account for leading 0x */
break;
@@ -418,15 +420,7 @@ vasnprintf (char *resultbuf, size_t *len
{
tmp = (char *) malloc (tmp_length);
if (tmp == NULL)
- {
- /* Out of memory. */
- if (!(result == resultbuf || result == NULL))
- free (result);
- freea (buf);
- CLEANUP ();
- errno = ENOMEM;
- return NULL;
- }
+ goto out_of_memory;
}
#endif
@@ -496,13 +490,13 @@ vasnprintf (char *resultbuf, size_t *len
/* Construct the arguments for calling snprintf or sprintf. */
prefix_count = 0;
- if (dp->width_arg_index >= 0)
+ if (dp->width_arg_index != SIZE_MAX)
{
if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
abort ();
prefixes[prefix_count++] =
a.arg[dp->width_arg_index].a.a_int;
}
- if (dp->precision_arg_index >= 0)
+ if (dp->precision_arg_index != SIZE_MAX)
{
if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
abort ();
@@ -717,7 +711,10 @@ vasnprintf (char *resultbuf, size_t *len
*and* it returns -1 (rather than the length
that would have been required) when the
buffer is too small. */
- size_t bigger_need = 2 * allocated + 12;
+ size_t bigger_need = xsum (allocated + 12,
+ allocated);
+ if (size_overflow_p (bigger_need))
+ goto out_of_memory;
ENSURE_ALLOCATION (bigger_need);
continue;
}
@@ -732,7 +729,6 @@ vasnprintf (char *resultbuf, size_t *len
{
if (!(result == resultbuf || result == NULL))
free (result);
- freea (buf);
CLEANUP ();
errno = EINVAL;
return NULL;
@@ -749,13 +745,15 @@ vasnprintf (char *resultbuf, size_t *len
if (count >= maxlen)
{
/* Need at least count bytes. But allocate
- proportionally, to avoid looping eternally if
+ at least 1 more byte, to avoid looping eternally if
snprintf() reports a too small count. */
- size_t n = length + count;
-
- if (n < 2 * allocated)
- n = 2 * allocated;
+ size_t n = xsum (length, count);
+ size_t allocated2 = xtimes (allocated, 2);
+ if (n < allocated2)
+ n = allocated2;
+ if (size_overflow_p (n))
+ goto out_of_memory;
ENSURE_ALLOCATION (n);
#if HAVE_SNPRINTF
continue;
@@ -792,9 +790,15 @@ vasnprintf (char *resultbuf, size_t *len
result = memory;
}
- freea (buf);
CLEANUP ();
*lengthp = length;
return result;
+
+ out_of_memory:
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ CLEANUP ();
+ errno = ENOMEM;
+ return NULL;
}
}
- [Bug-gnulib] proposed vasnprintf patches for address arithmetic and stack overflow,
Paul Eggert <=
- Re: [Bug-gnulib] proposed vasnprintf patches for address arithmetic and stack overflow, Bruno Haible, 2003/11/17
- Re: [Bug-gnulib] proposed vasnprintf patches for address arithmetic and stack overflow, Paul Eggert, 2003/11/17
- Re: [Bug-gnulib] proposed vasnprintf patches for address arithmetic and stack overflow, Bruno Haible, 2003/11/18
- Re: [Bug-gnulib] proposed vasnprintf patches for address arithmetic and stack overflow, Paul Eggert, 2003/11/18
- Re: [Bug-gnulib] proposed vasnprintf patches for address arithmetic and stack overflow, Bruno Haible, 2003/11/19
- Re: [Bug-gnulib] proposed vasnprintf patches for address arithmetic and stack overflow, Paul Eggert, 2003/11/20
- Re: [Bug-gnulib] proposed vasnprintf patches for address arithmetic and stack overflow, Bruno Haible, 2003/11/24
Re: [Bug-gnulib] proposed vasnprintf patches for address arithmetic and stack overflow, Bruno Haible, 2003/11/18