bug-gnulib
[Top][All Lists]
Advanced

[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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]