X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fprintf-parse.c;h=3d2fb175f2d4f9d84ba989234d4880d456800c21;hb=718b0598a7e9f5e9bdf3efc7e91e69a78e465327;hp=ad42e42c5c8569596dc50930bff4cda9b04524c2;hpb=dda38ff89ea6c5c28da197cebfbe2d5b510eafb5;p=gnulib.git diff --git a/lib/printf-parse.c b/lib/printf-parse.c index ad42e42c5..3d2fb175f 100644 --- a/lib/printf-parse.c +++ b/lib/printf-parse.c @@ -13,7 +13,7 @@ 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 @@ -40,6 +40,9 @@ /* 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 @@ -59,11 +62,11 @@ int 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; + 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; @@ -78,16 +81,22 @@ PRINTF_PARSE (const CHAR_T *format, 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; \ + 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, a_allocated * sizeof (argument)) \ - : malloc (a_allocated * sizeof (argument))); \ + ? realloc (a->arg, memory_size) \ + : malloc (memory_size)); \ if (memory == NULL) \ /* Out of memory. */ \ goto error; \ @@ -107,7 +116,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) CHAR_T c = *cp++; if (c == '%') { - int arg_index = -1; + size_t arg_index = ARG_NONE; DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */ /* Initialize the next directive. */ @@ -115,11 +124,11 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) 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') @@ -130,13 +139,16 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) ; 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; } @@ -197,24 +209,32 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) ; 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++) @@ -246,24 +266,33 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) ; 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++) @@ -455,8 +484,13 @@ PRINTF_PARSE (const CHAR_T *format, 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; @@ -466,10 +500,15 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) d->count++; if (d->count >= d_allocated) { + size_t memory_size; DIRECTIVE *memory; - d_allocated = 2 * d_allocated; - memory = realloc (d->dir, d_allocated * sizeof (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 = realloc (d->dir, memory_size); if (memory == NULL) /* Out of memory. */ goto error;