1 diff -Nrup a/stdio-common/bug22.c b/stdio-common/bug22.c
2 --- a/stdio-common/bug22.c 2010-05-04 05:27:23.000000000 -0600
3 +++ b/stdio-common/bug22.c 2012-08-03 13:56:40.887829210 -0600
12 +/* (INT_MAX / 2) + 2 */
13 +#define N2 1073741825
16 +#define N3 2147483644
18 #define STRINGIFY(S) #S
19 #define MAKE_STR(S) STRINGIFY(S)
21 #define SN MAKE_STR(N)
22 +#define SN2 MAKE_STR(N2)
23 +#define SN3 MAKE_STR(N3)
27 @@ -20,13 +30,27 @@ do_test (void)
31 - ret = fprintf (fp, "%" SN "d%" SN "d", 1, 1);
32 + ret = fprintf (fp, "%" SN "d", 1);
33 + printf ("ret = %d\n", ret);
34 + if (ret != -1 || errno != EOVERFLOW)
37 + ret = fprintf (fp, "%." SN "d", 1);
38 + printf ("ret = %d\n", ret);
39 + if (ret != -1 || errno != EOVERFLOW)
42 + ret = fprintf (fp, "%." SN3 "d", 1);
43 + printf ("ret = %d\n", ret);
44 + if (ret != -1 || errno != EOVERFLOW)
47 + ret = fprintf (fp, "%" SN2 "d%" SN2 "d", 1, 1);
48 printf ("ret = %d\n", ret);
51 + return ret != -1 || errno != EOVERFLOW;
56 #define TEST_FUNCTION do_test ()
57 #include "../test-skeleton.c"
58 diff -Nrup a/stdio-common/printf-parse.h b/stdio-common/printf-parse.h
59 --- a/stdio-common/printf-parse.h 2010-05-04 05:27:23.000000000 -0600
60 +++ b/stdio-common/printf-parse.h 2012-08-03 13:57:31.932638761 -0600
62 Lesser General Public License for more details.
64 You should have received a copy of the GNU Lesser General Public
65 - License along with the GNU C Library; if not, write to the Free
66 - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
68 + License along with the GNU C Library; if not, see
69 + <http://www.gnu.org/licenses/>. */
73 @@ -69,16 +68,27 @@ union printf_arg
74 #ifndef DONT_NEED_READ_INT
75 /* Read a simple integer from a string and update the string pointer.
76 It is assumed that the first character is a digit. */
79 read_int (const UCHAR_T * *pstr)
81 - unsigned int retval = **pstr - L_('0');
82 + int retval = **pstr - L_('0');
84 while (ISDIGIT (*++(*pstr)))
87 - retval += **pstr - L_('0');
91 + if (INT_MAX / 10 < retval)
95 + int digit = **pstr - L_('0');
98 + if (INT_MAX - digit < retval)
107 diff -Nrup a/stdio-common/printf-parsemb.c b/stdio-common/printf-parsemb.c
108 --- a/stdio-common/printf-parsemb.c 2010-05-04 05:27:23.000000000 -0600
109 +++ b/stdio-common/printf-parsemb.c 2012-08-03 13:58:44.683366361 -0600
111 Lesser General Public License for more details.
113 You should have received a copy of the GNU Lesser General Public
114 - License along with the GNU C Library; if not, write to the Free
115 - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
117 + License along with the GNU C Library; if not, see
118 + <http://www.gnu.org/licenses/>. */
122 @@ -88,12 +87,15 @@ __parse_one_specmb (const UCHAR_T *forma
124 n = read_int (&format);
126 - if (n > 0 && *format == L_('$'))
127 + if (n != 0 && *format == L_('$'))
128 /* Is positional parameter. */
130 ++format; /* Skip the '$'. */
131 - spec->data_arg = n - 1;
132 - *max_ref_arg = MAX (*max_ref_arg, n);
135 + spec->data_arg = n - 1;
136 + *max_ref_arg = MAX (*max_ref_arg, n);
140 /* Oops; that was actually the width and/or 0 padding flag.
141 @@ -161,10 +163,13 @@ __parse_one_specmb (const UCHAR_T *forma
142 /* The width argument might be found in a positional parameter. */
143 n = read_int (&format);
145 - if (n > 0 && *format == L_('$'))
146 + if (n != 0 && *format == L_('$'))
148 - spec->width_arg = n - 1;
149 - *max_ref_arg = MAX (*max_ref_arg, n);
152 + spec->width_arg = n - 1;
153 + *max_ref_arg = MAX (*max_ref_arg, n);
155 ++format; /* Skip '$'. */
158 @@ -178,9 +183,13 @@ __parse_one_specmb (const UCHAR_T *forma
161 else if (ISDIGIT (*format))
162 - /* Constant width specification. */
163 - spec->info.width = read_int (&format);
165 + int n = read_int (&format);
167 + /* Constant width specification. */
169 + spec->info.width = n;
171 /* Get the precision. */
173 /* -1 means none given; 0 means explicit 0. */
174 @@ -197,10 +206,13 @@ __parse_one_specmb (const UCHAR_T *forma
176 n = read_int (&format);
178 - if (n > 0 && *format == L_('$'))
179 + if (n != 0 && *format == L_('$'))
181 - spec->prec_arg = n - 1;
182 - *max_ref_arg = MAX (*max_ref_arg, n);
185 + spec->prec_arg = n - 1;
186 + *max_ref_arg = MAX (*max_ref_arg, n);
191 @@ -214,7 +226,12 @@ __parse_one_specmb (const UCHAR_T *forma
194 else if (ISDIGIT (*format))
195 - spec->info.prec = read_int (&format);
197 + int n = read_int (&format);
200 + spec->info.prec = n;
203 /* "%.?" is treated like "%.0?". */
205 @@ -295,9 +312,9 @@ __parse_one_specmb (const UCHAR_T *forma
206 /* We don't try to get the types for all arguments if the format
207 uses more than one. The normal case is covered though. If
208 the call returns -1 we continue with the normal specifiers. */
209 - || (spec->ndata_args = (*__printf_arginfo_table[spec->info.spec])
210 - (&spec->info, 1, &spec->data_arg_type,
212 + || (int) (spec->ndata_args = (*__printf_arginfo_table[spec->info.spec])
213 + (&spec->info, 1, &spec->data_arg_type,
216 /* Find the data argument types of a built-in spec. */
217 spec->ndata_args = 1;
218 diff -Nrup a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
219 --- a/stdio-common/vfprintf.c 2012-08-03 13:31:26.605168350 -0600
220 +++ b/stdio-common/vfprintf.c 2012-08-03 14:09:26.836725512 -0600
222 -/* Copyright (C) 1991-2008, 2009 Free Software Foundation, Inc.
223 +/* Copyright (C) 1991-2012 Free Software Foundation, Inc.
224 This file is part of the GNU C Library.
226 The GNU C Library is free software; you can redistribute it and/or
228 Lesser General Public License for more details.
230 You should have received a copy of the GNU Lesser General Public
231 - License along with the GNU C Library; if not, write to the Free
232 - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
234 + License along with the GNU C Library; if not, see
235 + <http://www.gnu.org/licenses/>. */
241 unsigned int _val = val; \
242 assert ((unsigned int) done < (unsigned int) INT_MAX); \
243 - if (__builtin_expect ((unsigned int) INT_MAX - (unsigned int) done \
245 + if (__builtin_expect (INT_MAX - done < _val, 0)) \
248 + __set_errno (EOVERFLOW); \
252 @@ -141,12 +140,17 @@
255 assert ((size_t) done <= (size_t) INT_MAX); \
256 - if ((size_t) PUT (s, (String), (Len)) != (size_t) (Len) \
257 - || (size_t) INT_MAX - (size_t) done < (size_t) (Len)) \
258 + if ((size_t) PUT (s, (String), (Len)) != (size_t) (Len)) \
263 + if (__builtin_expect (INT_MAX - done < (Len), 0)) \
266 + __set_errno (EOVERFLOW); \
272 @@ -1435,10 +1439,21 @@ vfprintf (FILE *s, const CHAR_T *format,
273 const UCHAR_T *tmp; /* Temporary value. */
276 - if (ISDIGIT (*tmp) && read_int (&tmp) && *tmp == L_('$'))
277 - /* The width comes from a positional parameter. */
278 - goto do_positional;
279 + if (ISDIGIT (*tmp))
281 + int pos = read_int (&tmp);
285 + __set_errno (EOVERFLOW);
290 + if (pos && *tmp == L_('$'))
291 + /* The width comes from a positional parameter. */
292 + goto do_positional;
294 width = va_arg (ap, int);
296 /* Negative width means left justified. */
297 @@ -1449,9 +1464,9 @@ vfprintf (FILE *s, const CHAR_T *format,
301 - if (__builtin_expect (width >= (size_t) -1 / sizeof (CHAR_T) - 32, 0))
302 + if (__builtin_expect (width >= INT_MAX / sizeof (CHAR_T) - 32, 0))
304 - __set_errno (ERANGE);
305 + __set_errno (EOVERFLOW);
309 @@ -1481,9 +1496,10 @@ vfprintf (FILE *s, const CHAR_T *format,
311 width = read_int (&f);
313 - if (__builtin_expect (width >= (size_t) -1 / sizeof (CHAR_T) - 32, 0))
314 + if (__builtin_expect (width == -1
315 + || width >= INT_MAX / sizeof (CHAR_T) - 32, 0))
317 - __set_errno (ERANGE);
318 + __set_errno (EOVERFLOW);
322 @@ -1518,10 +1534,21 @@ vfprintf (FILE *s, const CHAR_T *format,
323 const UCHAR_T *tmp; /* Temporary value. */
326 - if (ISDIGIT (*tmp) && read_int (&tmp) > 0 && *tmp == L_('$'))
327 - /* The precision comes from a positional parameter. */
328 - goto do_positional;
329 + if (ISDIGIT (*tmp))
331 + int pos = read_int (&tmp);
335 + __set_errno (EOVERFLOW);
340 + if (pos && *tmp == L_('$'))
341 + /* The precision comes from a positional parameter. */
342 + goto do_positional;
344 prec = va_arg (ap, int);
346 /* If the precision is negative the precision is omitted. */
347 @@ -1529,15 +1556,26 @@ vfprintf (FILE *s, const CHAR_T *format,
350 else if (ISDIGIT (*f))
351 - prec = read_int (&f);
353 + prec = read_int (&f);
355 + /* The precision was specified in this case as an extremely
356 + large positive value. */
359 + __set_errno (EOVERFLOW);
367 && prec > sizeof (work_buffer) / sizeof (work_buffer[0]) - 32)
369 - if (__builtin_expect (prec >= (size_t) -1 / sizeof (CHAR_T) - 32, 0))
370 + if (__builtin_expect (prec >= INT_MAX / sizeof (CHAR_T) - 32, 0))
372 - __set_errno (ERANGE);
373 + __set_errno (EOVERFLOW);
377 @@ -1722,13 +1760,13 @@ do_positional:
378 nargs = MAX (nargs, max_ref_arg);
379 /* Calculate total size needed to represent a single argument across
380 all three argument-related arrays. */
381 - bytes_per_arg = sizeof (*args_value) + sizeof (*args_size)
382 - + sizeof (*args_type);
383 + bytes_per_arg = (sizeof (*args_value) + sizeof (*args_size)
384 + + sizeof (*args_type));
386 /* Check for potential integer overflow. */
387 - if (__builtin_expect (nargs > SIZE_MAX / bytes_per_arg, 0))
388 + if (__builtin_expect (nargs > INT_MAX / bytes_per_arg, 0))
390 - __set_errno (ERANGE);
391 + __set_errno (EOVERFLOW);
395 @@ -1746,6 +1784,8 @@ do_positional:
399 + /* Set up the remaining two arrays to each point past the end of the
400 + prior array, since space for all three has been allocated now. */
401 args_size = &args_value[nargs].pa_int;
402 args_type = &args_size[nargs];
403 memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0',