X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fprintf-parse.c;h=f5cdb6e5b51173dc1448d5639e908ef1888c14c5;hb=bfee08023a94899768c682d94a6ff2d702fa4f02;hp=51b08bbb0a13b3dc41c4037dfae97e9a2b4ca6dc;hpb=757bd39e4b07efaefaef3ef11027b7b7b40f5911;p=gnulib.git diff --git a/lib/printf-parse.c b/lib/printf-parse.c index 51b08bbb0..f5cdb6e5b 100644 --- a/lib/printf-parse.c +++ b/lib/printf-parse.c @@ -1,5 +1,5 @@ /* Formatted output to strings. - Copyright (C) 1999-2000, 2002-2003 Free Software Foundation, Inc. + Copyright (C) 1999-2000, 2002-2003, 2006-2007 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 @@ -13,14 +13,16 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifdef HAVE_CONFIG_H -# include -#endif +#include /* Specification. */ -#include "printf-parse.h" +#if WIDE_CHAR_VERSION +# include "wprintf-parse.h" +#else +# include "printf-parse.h" +#endif /* Get size_t, NULL. */ #include @@ -36,22 +38,37 @@ /* malloc(), realloc(), free(). */ #include +/* Checked size_t computations. */ +#include "xsize.h" + +#if WIDE_CHAR_VERSION +# define PRINTF_PARSE wprintf_parse +# define CHAR_T wchar_t +# define DIRECTIVE wchar_t_directive +# define DIRECTIVES wchar_t_directives +#else +# define PRINTF_PARSE printf_parse +# define CHAR_T char +# define DIRECTIVE char_directive +# define DIRECTIVES char_directives +#endif + #ifdef STATIC STATIC #endif int -printf_parse (const char *format, char_directives *d, arguments *a) +PRINTF_PARSE (const CHAR_T *format, 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; + const CHAR_T *cp = format; /* pointer into format */ + 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; - d->dir = malloc (d_allocated * sizeof (char_directive)); + d->dir = (DIRECTIVE *) malloc (d_allocated * sizeof (DIRECTIVE)); if (d->dir == NULL) /* Out of memory. */ return -1; @@ -62,16 +79,22 @@ printf_parse (const char *format, char_directives *d, arguments *a) #define REGISTER_ARG(_index_,_type_) \ { \ - unsigned int n = (_index_); \ + size_t n = (_index_); \ if (n >= a_allocated) \ { \ + size_t memory_size; \ argument *memory; \ - a_allocated = 2 * a_allocated; \ + \ + a_allocated = xtimes (a_allocated, 2); \ if (a_allocated <= n) \ - a_allocated = n + 1; \ - memory = (a->arg \ - ? realloc (a->arg, a_allocated * sizeof (argument)) \ - : malloc (a_allocated * sizeof (argument))); \ + 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 = (argument *) (a->arg \ + ? realloc (a->arg, memory_size) \ + : malloc (memory_size)); \ if (memory == NULL) \ /* Out of memory. */ \ goto error; \ @@ -88,39 +111,42 @@ printf_parse (const char *format, char_directives *d, arguments *a) while (*cp != '\0') { - char c = *cp++; + CHAR_T c = *cp++; if (c == '%') { - int arg_index = -1; - char_directive *dp = &d->dir[d->count];/* pointer to next directive */ + size_t arg_index = ARG_NONE; + DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */ /* Initialize the next directive. */ dp->dir_start = cp - 1; dp->flags = 0; dp->width_start = NULL; dp->width_end = NULL; - dp->width_arg_index = -1; + dp->width_arg_index = ARG_NONE; dp->precision_start = NULL; dp->precision_end = NULL; - dp->precision_arg_index = -1; - dp->arg_index = -1; + dp->precision_arg_index = ARG_NONE; + dp->arg_index = ARG_NONE; /* Test for positional argument. */ if (*cp >= '0' && *cp <= '9') { - const char *np; + const CHAR_T *np; for (np = cp; *np >= '0' && *np <= '9'; np++) ; if (*np == '$') { - unsigned int n = 0; + size_t n = 0; for (np = cp; *np >= '0' && *np <= '9'; np++) - n = 10 * n + (*np - '0'); + n = xsum (xtimes (n, 10), *np - '0'); if (n == 0) /* Positional argument 0. */ goto error; + if (size_overflow_p (n)) + /* n too large, would lead to out of memory later. */ + goto error; arg_index = n - 1; cp = np + 1; } @@ -175,30 +201,38 @@ printf_parse (const char *format, char_directives *d, arguments *a) /* Test for positional argument. */ if (*cp >= '0' && *cp <= '9') { - const char *np; + const CHAR_T *np; for (np = cp; *np >= '0' && *np <= '9'; np++) ; if (*np == '$') { - unsigned int n = 0; + size_t n = 0; for (np = cp; *np >= '0' && *np <= '9'; np++) - n = 10 * n + (*np - '0'); + n = xsum (xtimes (n, 10), *np - '0'); if (n == 0) /* Positional argument 0. */ goto error; + if (size_overflow_p (n)) + /* 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 == ARG_NONE) + { + dp->width_arg_index = arg_posn++; + if (dp->width_arg_index == ARG_NONE) + /* arg_posn wrapped around. */ + goto error; + } 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++) @@ -224,30 +258,39 @@ printf_parse (const char *format, char_directives *d, arguments *a) /* Test for positional argument. */ if (*cp >= '0' && *cp <= '9') { - const char *np; + const CHAR_T *np; for (np = cp; *np >= '0' && *np <= '9'; np++) ; if (*np == '$') { - unsigned int n = 0; + size_t n = 0; for (np = cp; *np >= '0' && *np <= '9'; np++) - n = 10 * n + (*np - '0'); + n = xsum (xtimes (n, 10), *np - '0'); if (n == 0) /* Positional argument 0. */ goto error; + if (size_overflow_p (n)) + /* 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 == ARG_NONE) + { + dp->precision_arg_index = arg_posn++; + if (dp->precision_arg_index == ARG_NONE) + /* arg_posn wrapped around. */ + goto error; + } 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++) @@ -283,7 +326,7 @@ printf_parse (const char *format, char_directives *d, arguments *a) flags += 8; cp++; } -#ifdef HAVE_INTMAX_T +#if HAVE_INTMAX_T else if (*cp == 'j') { if (sizeof (intmax_t) > sizeof (long)) @@ -339,11 +382,14 @@ printf_parse (const char *format, char_directives *d, arguments *a) switch (c) { case 'd': case 'i': -#ifdef HAVE_LONG_LONG +#if HAVE_LONG_LONG_INT + /* If 'long long' exists and is larger than 'long': */ if (flags >= 16 || (flags & 4)) type = TYPE_LONGLONGINT; else #endif + /* If 'long long' exists and is the same as 'long', we parse + "lld" into TYPE_LONGINT. */ if (flags >= 8) type = TYPE_LONGINT; else if (flags & 2) @@ -354,11 +400,14 @@ printf_parse (const char *format, char_directives *d, arguments *a) type = TYPE_INT; break; case 'o': case 'u': case 'x': case 'X': -#ifdef HAVE_LONG_LONG +#if HAVE_LONG_LONG_INT + /* If 'long long' exists and is larger than 'long': */ if (flags >= 16 || (flags & 4)) type = TYPE_ULONGLONGINT; else #endif + /* If 'unsigned long long' exists and is the same as + 'unsigned long', we parse "llu" into TYPE_ULONGINT. */ if (flags >= 8) type = TYPE_ULONGINT; else if (flags & 2) @@ -370,7 +419,7 @@ printf_parse (const char *format, char_directives *d, arguments *a) break; case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': case 'a': case 'A': -#ifdef HAVE_LONG_DOUBLE +#if HAVE_LONG_DOUBLE if (flags >= 16 || (flags & 4)) type = TYPE_LONGDOUBLE; else @@ -379,7 +428,7 @@ printf_parse (const char *format, char_directives *d, arguments *a) break; case 'c': if (flags >= 8) -#ifdef HAVE_WINT_T +#if HAVE_WINT_T type = TYPE_WIDE_CHAR; #else goto error; @@ -387,7 +436,7 @@ printf_parse (const char *format, char_directives *d, arguments *a) else type = TYPE_CHAR; break; -#ifdef HAVE_WINT_T +#if HAVE_WINT_T case 'C': type = TYPE_WIDE_CHAR; c = 'c'; @@ -395,7 +444,7 @@ printf_parse (const char *format, char_directives *d, arguments *a) #endif case 's': if (flags >= 8) -#ifdef HAVE_WCHAR_T +#if HAVE_WCHAR_T type = TYPE_WIDE_STRING; #else goto error; @@ -403,7 +452,7 @@ printf_parse (const char *format, char_directives *d, arguments *a) else type = TYPE_STRING; break; -#ifdef HAVE_WCHAR_T +#if HAVE_WCHAR_T case 'S': type = TYPE_WIDE_STRING; c = 's'; @@ -413,11 +462,14 @@ printf_parse (const char *format, char_directives *d, arguments *a) type = TYPE_POINTER; break; case 'n': -#ifdef HAVE_LONG_LONG +#if HAVE_LONG_LONG_INT + /* If 'long long' exists and is larger than 'long': */ if (flags >= 16 || (flags & 4)) type = TYPE_COUNT_LONGLONGINT_POINTER; else #endif + /* If 'long long' exists and is the same as 'long', we parse + "lln" into TYPE_COUNT_LONGINT_POINTER. */ if (flags >= 8) type = TYPE_COUNT_LONGINT_POINTER; else if (flags & 2) @@ -439,8 +491,13 @@ printf_parse (const char *format, char_directives *d, arguments *a) if (type != TYPE_NONE) { dp->arg_index = arg_index; - if (dp->arg_index < 0) - dp->arg_index = arg_posn++; + if (dp->arg_index == ARG_NONE) + { + dp->arg_index = arg_posn++; + if (dp->arg_index == ARG_NONE) + /* arg_posn wrapped around. */ + goto error; + } REGISTER_ARG (dp->arg_index, type); } dp->conversion = c; @@ -450,10 +507,15 @@ printf_parse (const char *format, char_directives *d, arguments *a) d->count++; if (d->count >= d_allocated) { - char_directive *memory; + size_t memory_size; + DIRECTIVE *memory; - d_allocated = 2 * d_allocated; - memory = realloc (d->dir, d_allocated * sizeof (char_directive)); + d_allocated = xtimes (d_allocated, 2); + memory_size = xtimes (d_allocated, sizeof (DIRECTIVE)); + if (size_overflow_p (memory_size)) + /* Overflow, would lead to out of memory. */ + goto error; + memory = (DIRECTIVE *) realloc (d->dir, memory_size); if (memory == NULL) /* Out of memory. */ goto error; @@ -474,3 +536,8 @@ error: free (d->dir); return -1; } + +#undef DIRECTIVES +#undef DIRECTIVE +#undef CHAR_T +#undef PRINTF_PARSE