[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Bug-gnulib] proposed vasnprintf patches for address arithmetic and
From: |
Bruno Haible |
Subject: |
Re: [Bug-gnulib] proposed vasnprintf patches for address arithmetic and stack overflow |
Date: |
Mon, 17 Nov 2003 16:12:55 +0100 |
User-agent: |
KMail/1.5 |
Paul Eggert wrote:
> Here are some proposed patches for the vasnprintf module of gnulib.
Thanks a lot for these patches. I'm surprised how vulnerable against
overlong format strings or against format strings with junk 'width' or
'precision' specifications the code was.
The patch I'm committing is different from yours:
- I don't want to use an unsigned type where I was using 'int',
because that kills the well-known idiom of using "-1" denoting "no value".
The use of SIZE_MAX instead makes the code less understandable,
because in one place SIZE_MAX denotes overflow and in another place
it denotes "no value".
- Your uses of xsum and xtimes were incomplete: There were assignments
like "allocated = 2 * allocated;" that were not checked in your patch.
- Also "allocated = xsum (allocated + 12, allocated);" is incomplete:
it fails to diagnose overflow when allocated == (size_t)-8.
I'll deal with alloca tomorrow.
Bruno
2003-11-16 Paul Eggert <address@hidden>
Bruno Haible <address@hidden>
Protect against address arithmetic overflow.
* lib/printf-args.h: Include stddef.h.
(arguments): Change type of field 'count' to size_t.
* lib/printf-args.c (printf_fetchargs): Use size_t instead of
'unsigned int' where appropriate.
* lib/printf-parse.h: Include sys/types.h.
(char_directive): Change type of *arg_index fields to ssize_t.
(char_directives): Change type of fields 'count', max_*_length to
size_t.
* lib/printf-parse.c: Include sys/types.h and xsize.h.
(SSIZE_MAX): Define fallback value.
(PRINTF_PARSE): Use size_t instead of 'unsigned int' and ssize_t
instead of 'int' where appropriate. Check a_allocated, d_allocated
against overflow. Reject %m$ argument numbers > SSIZE_MAX + 1.
* lib/vasnprintf.c: Include xsize.h.
(VASNPRINTF): Use size_t instead of 'unsigned int' where appropriate.
Check alloca, malloc, realloc, ENSURE_ALLOCATION arguments against
overflow. Avoid wraparound when converting a width or precision from
decimal to binary.
* m4/vasnprintf.m4 (gl_PREREQ_PRINTF_PARSE): Require gt_TYPE_SSIZE_T.
* modules/vasnprintf (Files): Add m4/ssize_t.m4.
(Depends-on): Add xsize.
*** lib/printf-args.h 14 Jul 2003 22:44:04 -0000 1.2
--- lib/printf-args.h 17 Nov 2003 15:10:51 -0000
***************
*** 18,23 ****
--- 18,26 ----
#ifndef _PRINTF_ARGS_H
#define _PRINTF_ARGS_H
+ /* Get size_t. */
+ #include <stddef.h>
+
/* Get wchar_t. */
#ifdef HAVE_WCHAR_T
# include <stddef.h>
***************
*** 116,122 ****
typedef struct
{
! unsigned int count;
argument *arg;
}
arguments;
--- 119,125 ----
typedef struct
{
! size_t count;
argument *arg;
}
arguments;
*** lib/printf-args.c 14 Jul 2003 22:44:04 -0000 1.2
--- lib/printf-args.c 17 Nov 2003 15:10:51 -0000
***************
*** 28,34 ****
int
printf_fetchargs (va_list args, arguments *a)
{
! unsigned int i;
argument *ap;
for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++)
--- 28,34 ----
int
printf_fetchargs (va_list args, arguments *a)
{
! size_t i;
argument *ap;
for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++)
*** lib/printf-parse.h 14 Jul 2003 22:44:04 -0000 1.2
--- lib/printf-parse.h 17 Nov 2003 15:10:51 -0000
***************
*** 1,5 ****
/* Parse printf format string.
! Copyright (C) 1999, 2002 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
--- 1,5 ----
/* Parse printf format string.
! Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
***************
*** 20,25 ****
--- 20,28 ----
#include "printf-args.h"
+ /* Get ssize_t. */
+ #include <sys/types.h>
+
/* Flags */
#define FLAG_GROUP 1 /* ' flag */
***************
*** 37,58 ****
int flags;
const char* width_start;
const char* width_end;
! int width_arg_index;
const char* precision_start;
const char* precision_end;
! int 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;
}
char_directive;
/* A parsed format string. */
typedef struct
{
! unsigned int count;
char_directive *dir;
! unsigned int max_width_length;
! unsigned int max_precision_length;
}
char_directives;
--- 40,61 ----
int flags;
const char* width_start;
const char* width_end;
! ssize_t width_arg_index;
const char* precision_start;
const char* precision_end;
! ssize_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 */
! ssize_t arg_index;
}
char_directive;
/* A parsed format string. */
typedef struct
{
! size_t count;
char_directive *dir;
! size_t max_width_length;
! size_t max_precision_length;
}
char_directives;
*** lib/printf-parse.c 17 Nov 2003 14:56:31 -0000 1.3
--- lib/printf-parse.c 17 Nov 2003 15:10:51 -0000
***************
*** 29,34 ****
--- 29,37 ----
/* Get size_t, NULL. */
#include <stddef.h>
+ /* Get ssize_t. */
+ #include <sys/types.h>
+
/* Get intmax_t. */
#if HAVE_STDINT_H_WITH_UINTMAX
# include <stdint.h>
***************
*** 40,45 ****
--- 43,55 ----
/* malloc(), realloc(), free(). */
#include <stdlib.h>
+ /* Checked size_t computations. */
+ #include "xsize.h"
+
+ #ifndef SSIZE_MAX
+ # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
+ #endif
+
#if WIDE_CHAR_VERSION
# define PRINTF_PARSE wprintf_parse
# define CHAR_T wchar_t
***************
*** 59,69 ****
PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
{
const CHAR_T *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;
d->count = 0;
d_allocated = 1;
--- 69,79 ----
PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
{
const CHAR_T *cp = format; /* pointer into format */
! ssize_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;
***************
*** 78,93 ****
#define REGISTER_ARG(_index_,_type_) \
{ \
! unsigned int n = (_index_);
\
if (n >= a_allocated) \
{
\
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))); \
if (memory == NULL) \
/* Out of memory. */ \
goto error; \
--- 88,109 ----
#define REGISTER_ARG(_index_,_type_) \
{ \
! size_t n = (_index_); \
if (n >= a_allocated) \
{
\
+ size_t memory_size; \
argument *memory; \
! \
! a_allocated = xtimes (a_allocated, 2); \
if (a_allocated <= n) \
! a_allocated = xsum (n, 1); \
! memory_size = xtimes (a_allocated, sizeof (argument)); \
! if (size_overflow_p (memory_size)) \
! /* Overflow, would lead to out of memory. */ \
! goto error; \
memory = (a->arg \
! ? realloc (a->arg, memory_size) \
! : malloc (memory_size)); \
if (memory == NULL) \
/* Out of memory. */ \
goto error; \
***************
*** 107,113 ****
CHAR_T c = *cp++;
if (c == '%')
{
! int arg_index = -1;
DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */
/* Initialize the next directive. */
--- 123,129 ----
CHAR_T c = *cp++;
if (c == '%')
{
! ssize_t arg_index = -1;
DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */
/* Initialize the next directive. */
***************
*** 130,142 ****
;
if (*np == '$')
{
! unsigned int n = 0;
for (np = cp; *np >= '0' && *np <= '9'; np++)
! n = 10 * n + (*np - '0');
if (n == 0)
/* Positional argument 0. */
goto error;
arg_index = n - 1;
cp = np + 1;
}
--- 146,161 ----
;
if (*np == '$')
{
! size_t n = 0;
for (np = cp; *np >= '0' && *np <= '9'; np++)
! n = xsum (xtimes (n, 10), *np - '0');
if (n == 0)
/* Positional argument 0. */
goto error;
+ if (size_overflow_p (n) || n - 1 > SSIZE_MAX)
+ /* n too large, would lead to out of memory later. */
+ goto error;
arg_index = n - 1;
cp = np + 1;
}
***************
*** 197,220 ****
;
if (*np == '$')
{
! unsigned int n = 0;
for (np = cp; *np >= '0' && *np <= '9'; np++)
! n = 10 * n + (*np - '0');
if (n == 0)
/* Positional argument 0. */
goto error;
dp->width_arg_index = n - 1;
cp = np + 1;
}
}
if (dp->width_arg_index < 0)
! dp->width_arg_index = arg_posn++;
REGISTER_ARG (dp->width_arg_index, TYPE_INT);
}
else if (*cp >= '0' && *cp <= '9')
{
! unsigned int width_length;
dp->width_start = cp;
for (; *cp >= '0' && *cp <= '9'; cp++)
--- 216,247 ----
;
if (*np == '$')
{
! size_t n = 0;
for (np = cp; *np >= '0' && *np <= '9'; np++)
! n = xsum (xtimes (n, 10), *np - '0');
if (n == 0)
/* Positional argument 0. */
goto error;
+ if (size_overflow_p (n) || n - 1 > SSIZE_MAX)
+ /* n too large, would lead to out of memory later. */
+ goto error;
dp->width_arg_index = n - 1;
cp = np + 1;
}
}
if (dp->width_arg_index < 0)
! {
! dp->width_arg_index = arg_posn++;
! if (dp->width_arg_index < 0)
! /* arg_posn wrapped around at SSIZE_MAX. */
! goto error;
! }
REGISTER_ARG (dp->width_arg_index, TYPE_INT);
}
else if (*cp >= '0' && *cp <= '9')
{
! size_t width_length;
dp->width_start = cp;
for (; *cp >= '0' && *cp <= '9'; cp++)
***************
*** 246,269 ****
;
if (*np == '$')
{
! unsigned int n = 0;
for (np = cp; *np >= '0' && *np <= '9'; np++)
! n = 10 * n + (*np - '0');
if (n == 0)
/* Positional argument 0. */
goto error;
dp->precision_arg_index = n - 1;
cp = np + 1;
}
}
if (dp->precision_arg_index < 0)
! dp->precision_arg_index = arg_posn++;
REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
}
else
{
! unsigned int precision_length;
dp->precision_start = cp - 1;
for (; *cp >= '0' && *cp <= '9'; cp++)
--- 273,305 ----
;
if (*np == '$')
{
! size_t n = 0;
for (np = cp; *np >= '0' && *np <= '9'; np++)
! n = xsum (xtimes (n, 10), *np - '0');
if (n == 0)
/* Positional argument 0. */
goto error;
+ if (size_overflow_p (n) || n - 1 > SSIZE_MAX)
+ /* n too large, would lead to out of memory
+ later. */
+ goto error;
dp->precision_arg_index = n - 1;
cp = np + 1;
}
}
if (dp->precision_arg_index < 0)
! {
! dp->precision_arg_index = arg_posn++;
! if (dp->precision_arg_index < 0)
! /* arg_posn wrapped around at SSIZE_MAX. */
! goto error;
! }
REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
}
else
{
! size_t precision_length;
dp->precision_start = cp - 1;
for (; *cp >= '0' && *cp <= '9'; cp++)
***************
*** 456,462 ****
{
dp->arg_index = arg_index;
if (dp->arg_index < 0)
! dp->arg_index = arg_posn++;
REGISTER_ARG (dp->arg_index, type);
}
dp->conversion = c;
--- 492,503 ----
{
dp->arg_index = arg_index;
if (dp->arg_index < 0)
! {
! dp->arg_index = arg_posn++;
! if (dp->arg_index < 0)
! /* arg_posn wrapped around at SSIZE_MAX. */
! goto error;
! }
REGISTER_ARG (dp->arg_index, type);
}
dp->conversion = c;
***************
*** 466,475 ****
d->count++;
if (d->count >= d_allocated)
{
DIRECTIVE *memory;
! d_allocated = 2 * d_allocated;
! memory = realloc (d->dir, d_allocated * sizeof (DIRECTIVE));
if (memory == NULL)
/* Out of memory. */
goto error;
--- 507,524 ----
d->count++;
if (d->count >= d_allocated)
{
+ size_t memory_size;
DIRECTIVE *memory;
! d_allocated = xtimes (d_allocated, 2);
! if (size_overflow_p (d_allocated))
! /* Overflow, would lead to out of memory. */
! goto error;
! memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
! if (size_overflow_p (memory_size))
! /* Overflow, would lead to out of memory. */
! goto error;
! memory = realloc (d->dir, memory_size);
if (memory == NULL)
/* Out of memory. */
goto error;
*** lib/vasnprintf.c 17 Nov 2003 14:56:32 -0000 1.9
--- lib/vasnprintf.c 17 Nov 2003 15:10:51 -0000
***************
*** 48,53 ****
--- 48,56 ----
# include "printf-parse.h"
#endif
+ /* Checked size_t computations. */
+ #include "xsize.h"
+
/* For those losing systems which don't have 'alloca' we have to add
some additional code emulating it. */
#ifdef HAVE_ALLOCA
***************
*** 136,146 ****
}
{
CHAR_T *buf =
! (CHAR_T *) alloca ((7 + d.max_width_length + d.max_precision_length + 6)
! * sizeof (CHAR_T));
const CHAR_T *cp;
! unsigned int i;
DIRECTIVE *dp;
/* Output string accumulator. */
CHAR_T *result;
--- 139,150 ----
}
{
+ size_t buf_neededlength =
+ xsum4 (7, d.max_width_length, d.max_precision_length, 6);
CHAR_T *buf =
! (CHAR_T *) alloca (xtimes (buf_neededlength, sizeof (CHAR_T)));
const CHAR_T *cp;
! size_t i;
DIRECTIVE *dp;
/* Output string accumulator. */
CHAR_T *result;
***************
*** 162,189 ****
result is either == resultbuf or == NULL or malloc-allocated.
If length > 0, then result != NULL. */
#define ENSURE_ALLOCATION(needed) \
if ((needed) > allocated) \
{
\
CHAR_T *memory; \
\
! allocated = (allocated > 0 ? 2 * allocated : 12); \
if ((needed) > allocated) \
allocated = (needed); \
if (result == resultbuf || result == NULL) \
! memory = (CHAR_T *) malloc (allocated * sizeof (CHAR_T)); \
else \
! memory = (CHAR_T *) realloc (result, allocated * sizeof (CHAR_T)); \
! \
if (memory == NULL) \
! { \
! if (!(result == resultbuf || result == NULL)) \
! free (result); \
! freea (buf); \
! CLEANUP (); \
! errno = ENOMEM; \
! return NULL; \
! } \
if (result == resultbuf && length > 0) \
memcpy (memory, result, length * sizeof (CHAR_T)); \
result = memory; \
--- 166,191 ----
result is either == resultbuf or == NULL or malloc-allocated.
If length > 0, then result != NULL. */
+ /* Ensures that allocated >= needed. Aborts through a jump to
+ out_of_memory if needed is SIZE_MAX or otherwise too big. */
#define ENSURE_ALLOCATION(needed) \
if ((needed) > allocated) \
{
\
+ size_t memory_size; \
CHAR_T *memory; \
\
! allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \
if ((needed) > allocated) \
allocated = (needed); \
+ memory_size = xtimes (allocated, sizeof (CHAR_T)); \
+ if (size_overflow_p (memory_size)) \
+ goto out_of_memory; \
if (result == resultbuf || result == NULL) \
! memory = (CHAR_T *) malloc (memory_size); \
else \
! memory = (CHAR_T *) realloc (result, memory_size); \
if (memory == NULL) \
! goto out_of_memory; \
if (result == resultbuf && length > 0) \
memcpy (memory, result, length * sizeof (CHAR_T)); \
result = memory; \
***************
*** 194,203 ****
if (cp != dp->dir_start)
{
size_t n = dp->dir_start - cp;
! ENSURE_ALLOCATION (length + n);
memcpy (result + length, cp, n * sizeof (CHAR_T));
! length += n;
}
if (i == d.count)
break;
--- 196,206 ----
if (cp != dp->dir_start)
{
size_t n = dp->dir_start - cp;
+ size_t augmented_length = xsum (length, n);
! ENSURE_ALLOCATION (augmented_length);
memcpy (result + length, cp, n * sizeof (CHAR_T));
! length = augmented_length;
}
if (i == d.count)
break;
***************
*** 205,215 ****
/* Execute a single directive. */
if (dp->conversion == '%')
{
if (!(dp->arg_index < 0))
abort ();
! ENSURE_ALLOCATION (length + 1);
result[length] = '%';
! length += 1;
}
else
{
--- 208,221 ----
/* Execute a single directive. */
if (dp->conversion == '%')
{
+ size_t augmented_length;
+
if (!(dp->arg_index < 0))
abort ();
! augmented_length = xsum (length, 1);
! ENSURE_ALLOCATION (augmented_length);
result[length] = '%';
! length = augmented_length;
}
else
{
***************
*** 248,262 ****
unsigned int prefix_count;
int prefixes[2];
#if !USE_SNPRINTF
! unsigned int tmp_length;
CHAR_T tmpbuf[700];
CHAR_T *tmp;
/* Allocate a temporary buffer of sufficient size for calling
sprintf. */
{
! unsigned int width;
! unsigned int precision;
width = 0;
if (dp->width_start != dp->width_end)
--- 254,268 ----
unsigned int prefix_count;
int prefixes[2];
#if !USE_SNPRINTF
! size_t tmp_length;
CHAR_T tmpbuf[700];
CHAR_T *tmp;
/* Allocate a temporary buffer of sufficient size for calling
sprintf. */
{
! size_t width;
! size_t precision;
width = 0;
if (dp->width_start != dp->width_end)
***************
*** 268,281 ****
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);
}
else
{
const CHAR_T *digitp = dp->width_start;
do
! width = width * 10 + (*digitp++ - '0');
while (digitp != dp->width_end);
}
}
--- 274,287 ----
if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
abort ();
arg = a.arg[dp->width_arg_index].a.a_int;
! width = (arg < 0 ? (unsigned int) (-arg) : arg);
}
else
{
const CHAR_T *digitp = dp->width_start;
do
! width = xsum (xtimes (width, 10), *digitp++ - '0');
while (digitp != dp->width_end);
}
}
***************
*** 298,304 ****
precision = 0;
do
! precision = precision * 10 + (*digitp++ - '0');
while (digitp != dp->precision_end);
}
}
--- 304,310 ----
precision = 0;
do
! precision = xsum (xtimes (precision, 10), *digitp++
- '0');
while (digitp != dp->precision_end);
}
}
***************
*** 399,405 ****
* 2 /* estimate for FLAG_GROUP */
)
+ 1 /* turn floor into ceil */
- + precision
+ 10; /* sign, decimal point etc. */
else
# endif
--- 405,410 ----
***************
*** 409,423 ****
* 2 /* estimate for FLAG_GROUP */
)
+ 1 /* turn floor into ceil */
- + precision
+ 10; /* sign, decimal point etc. */
break;
case 'e': case 'E': case 'g': case 'G':
case 'a': case 'A':
tmp_length =
! precision
! + 12; /* sign, decimal point, exponent etc. */
break;
case 'c':
--- 414,428 ----
* 2 /* estimate for FLAG_GROUP */
)
+ 1 /* turn floor into ceil */
+ 10; /* sign, decimal point etc. */
+ tmp_length = xsum (tmp_length, precision);
break;
case 'e': case 'E': case 'g': case 'G':
case 'a': case 'A':
tmp_length =
! 12; /* sign, decimal point, exponent etc. */
! tmp_length = xsum (tmp_length, precision);
break;
case 'c':
***************
*** 432,445 ****
case 's':
# ifdef HAVE_WCHAR_T
if (type == TYPE_WIDE_STRING)
! # if WIDE_CHAR_VERSION
! tmp_length =
! local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
! # else
! tmp_length =
! local_wcslen (a.arg[dp->arg_index].a.a_wide_string)
! * MB_CUR_MAX;
# endif
else
# endif
tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
--- 437,450 ----
case 's':
# ifdef HAVE_WCHAR_T
if (type == TYPE_WIDE_STRING)
! {
! tmp_length =
! local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
!
! # if !WIDE_CHAR_VERSION
! tmp_length = xtimes (tmp_length, MB_CUR_MAX);
# endif
+ }
else
# endif
tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
***************
*** 461,484 ****
if (tmp_length < width)
tmp_length = width;
! tmp_length++; /* account for trailing NUL */
}
if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
tmp = tmpbuf;
else
{
! tmp = (CHAR_T *) malloc (tmp_length * sizeof (CHAR_T));
if (tmp == NULL)
! {
! /* Out of memory. */
! if (!(result == resultbuf || result == NULL))
! free (result);
! freea (buf);
! CLEANUP ();
! errno = ENOMEM;
! return NULL;
! }
}
#endif
--- 466,487 ----
if (tmp_length < width)
tmp_length = width;
! tmp_length = xsum (tmp_length, 1); /* account for trailing
NUL */
}
if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
tmp = tmpbuf;
else
{
! size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
!
! if (size_overflow_p (tmp_memsize))
! /* Overflow, would lead to out of memory. */
! goto out_of_memory;
! tmp = (CHAR_T *) malloc (tmp_memsize);
if (tmp == NULL)
! /* Out of memory. */
! goto out_of_memory;
}
#endif
***************
*** 564,570 ****
#if USE_SNPRINTF
/* Prepare checking whether snprintf returns the count
via %n. */
! ENSURE_ALLOCATION (length + 1);
result[length] = '\0';
#endif
--- 567,573 ----
#if USE_SNPRINTF
/* Prepare checking whether snprintf returns the count
via %n. */
! ENSURE_ALLOCATION (xsum (length, 1));
result[length] = '\0';
#endif
***************
*** 769,775 ****
*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;
ENSURE_ALLOCATION (bigger_need);
continue;
}
--- 772,779 ----
*and* it returns -1 (rather than the length
that would have been required) when the
buffer is too small. */
! size_t bigger_need =
! xsum (xtimes (allocated, 2), 12);
ENSURE_ALLOCATION (bigger_need);
continue;
}
***************
*** 803,812 ****
/* Need at least count bytes. But allocate
proportionally, to avoid looping eternally if
snprintf() reports a too small count. */
! size_t n = length + count;
!
! if (n < 2 * allocated)
! n = 2 * allocated;
ENSURE_ALLOCATION (n);
#if USE_SNPRINTF
--- 807,814 ----
/* Need at least count bytes. But allocate
proportionally, to avoid looping eternally if
snprintf() reports a too small count. */
! size_t n =
! xmax (xsum (length, count), xtimes (allocated, 2));
ENSURE_ALLOCATION (n);
#if USE_SNPRINTF
***************
*** 831,837 ****
}
/* Add the final NUL. */
! ENSURE_ALLOCATION (length + 1);
result[length] = '\0';
if (result != resultbuf && length + 1 < allocated)
--- 833,839 ----
}
/* Add the final NUL. */
! ENSURE_ALLOCATION (xsum (length, 1));
result[length] = '\0';
if (result != resultbuf && length + 1 < allocated)
***************
*** 848,853 ****
--- 850,863 ----
CLEANUP ();
*lengthp = length;
return result;
+
+ out_of_memory:
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ freea (buf);
+ CLEANUP ();
+ errno = ENOMEM;
+ return NULL;
}
}
*** m4/vasnprintf.m4 11 Aug 2003 13:02:26 -0000 1.2
--- m4/vasnprintf.m4 17 Nov 2003 15:10:51 -0000
***************
*** 1,4 ****
! # vasnprintf.m4 serial 2
dnl Copyright (C) 2002-2003 Free Software Foundation, Inc.
dnl This file is free software, distributed under the terms of the GNU
dnl General Public License. As a special exception to the GNU General
--- 1,4 ----
! # vasnprintf.m4 serial 3
dnl Copyright (C) 2002-2003 Free Software Foundation, Inc.
dnl This file is free software, distributed under the terms of the GNU
dnl General Public License. As a special exception to the GNU General
***************
*** 38,43 ****
--- 38,44 ----
AC_REQUIRE([gt_TYPE_WCHAR_T])
AC_REQUIRE([gt_TYPE_WINT_T])
AC_REQUIRE([AC_TYPE_SIZE_T])
+ AC_REQUIRE([gt_TYPE_SSIZE_T])
AC_CHECK_TYPES(ptrdiff_t)
AC_REQUIRE([gt_AC_TYPE_INTMAX_T])
])
*** modules/vasnprintf 30 Jan 2003 13:48:21 -0000 1.1
--- modules/vasnprintf 17 Nov 2003 15:10:51 -0000
***************
*** 15,24 ****
--- 15,26 ----
m4/wint_t.m4
m4/longlong.m4
m4/intmax_t.m4
+ m4/ssize_t.m4
m4/vasnprintf.m4
Depends-on:
alloca
+ xsize
configure.ac:
gl_FUNC_VASNPRINTF
- [Bug-gnulib] proposed vasnprintf patches for address arithmetic and stack overflow, Paul Eggert, 2003/11/15
- Re: [Bug-gnulib] proposed vasnprintf patches for address arithmetic and stack overflow,
Bruno Haible <=
- 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