]>
Commit | Line | Data |
---|---|---|
30a4e827 MT |
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 | |
4 | @@ -1,12 +1,22 @@ | |
5 | /* BZ #5424 */ | |
6 | #include <stdio.h> | |
7 | +#include <errno.h> | |
8 | ||
9 | +/* INT_MAX + 1 */ | |
10 | #define N 2147483648 | |
11 | ||
12 | +/* (INT_MAX / 2) + 2 */ | |
13 | +#define N2 1073741825 | |
14 | + | |
15 | +/* INT_MAX - 3 */ | |
16 | +#define N3 2147483644 | |
17 | + | |
18 | #define STRINGIFY(S) #S | |
19 | #define MAKE_STR(S) STRINGIFY(S) | |
20 | ||
21 | #define SN MAKE_STR(N) | |
22 | +#define SN2 MAKE_STR(N2) | |
23 | +#define SN3 MAKE_STR(N3) | |
24 | ||
25 | static int | |
26 | do_test (void) | |
27 | @@ -20,13 +30,27 @@ do_test (void) | |
28 | return 1; | |
29 | } | |
30 | ||
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) | |
35 | + return 1; | |
36 | + | |
37 | + ret = fprintf (fp, "%." SN "d", 1); | |
38 | + printf ("ret = %d\n", ret); | |
39 | + if (ret != -1 || errno != EOVERFLOW) | |
40 | + return 1; | |
41 | + | |
42 | + ret = fprintf (fp, "%." SN3 "d", 1); | |
43 | + printf ("ret = %d\n", ret); | |
44 | + if (ret != -1 || errno != EOVERFLOW) | |
45 | + return 1; | |
46 | ||
47 | + ret = fprintf (fp, "%" SN2 "d%" SN2 "d", 1, 1); | |
48 | printf ("ret = %d\n", ret); | |
49 | ||
50 | - return ret != -1; | |
51 | + return ret != -1 || errno != EOVERFLOW; | |
52 | } | |
53 | ||
54 | -#define TIMEOUT 30 | |
55 | +#define TIMEOUT 60 | |
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 | |
61 | @@ -14,9 +14,8 @@ | |
62 | Lesser General Public License for more details. | |
63 | ||
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 | |
67 | - 02111-1307 USA. */ | |
68 | + License along with the GNU C Library; if not, see | |
69 | + <http://www.gnu.org/licenses/>. */ | |
70 | ||
71 | #include <printf.h> | |
72 | #include <stdint.h> | |
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. */ | |
77 | -static unsigned int | |
78 | +static int | |
79 | read_int (const UCHAR_T * *pstr) | |
80 | { | |
81 | - unsigned int retval = **pstr - L_('0'); | |
82 | + int retval = **pstr - L_('0'); | |
83 | ||
84 | while (ISDIGIT (*++(*pstr))) | |
85 | - { | |
86 | - retval *= 10; | |
87 | - retval += **pstr - L_('0'); | |
88 | - } | |
89 | + if (retval >= 0) | |
90 | + { | |
91 | + if (INT_MAX / 10 < retval) | |
92 | + retval = -1; | |
93 | + else | |
94 | + { | |
95 | + int digit = **pstr - L_('0'); | |
96 | + | |
97 | + retval *= 10; | |
98 | + if (INT_MAX - digit < retval) | |
99 | + retval = -1; | |
100 | + else | |
101 | + retval += digit; | |
102 | + } | |
103 | + } | |
104 | ||
105 | return retval; | |
106 | } | |
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 | |
110 | @@ -13,9 +13,8 @@ | |
111 | Lesser General Public License for more details. | |
112 | ||
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 | |
116 | - 02111-1307 USA. */ | |
117 | + License along with the GNU C Library; if not, see | |
118 | + <http://www.gnu.org/licenses/>. */ | |
119 | ||
120 | #include <ctype.h> | |
121 | #include <limits.h> | |
122 | @@ -88,12 +87,15 @@ __parse_one_specmb (const UCHAR_T *forma | |
123 | ||
124 | n = read_int (&format); | |
125 | ||
126 | - if (n > 0 && *format == L_('$')) | |
127 | + if (n != 0 && *format == L_('$')) | |
128 | /* Is positional parameter. */ | |
129 | { | |
130 | ++format; /* Skip the '$'. */ | |
131 | - spec->data_arg = n - 1; | |
132 | - *max_ref_arg = MAX (*max_ref_arg, n); | |
133 | + if (n != -1) | |
134 | + { | |
135 | + spec->data_arg = n - 1; | |
136 | + *max_ref_arg = MAX (*max_ref_arg, n); | |
137 | + } | |
138 | } | |
139 | else | |
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); | |
144 | ||
145 | - if (n > 0 && *format == L_('$')) | |
146 | + if (n != 0 && *format == L_('$')) | |
147 | { | |
148 | - spec->width_arg = n - 1; | |
149 | - *max_ref_arg = MAX (*max_ref_arg, n); | |
150 | + if (n != -1) | |
151 | + { | |
152 | + spec->width_arg = n - 1; | |
153 | + *max_ref_arg = MAX (*max_ref_arg, n); | |
154 | + } | |
155 | ++format; /* Skip '$'. */ | |
156 | } | |
157 | } | |
158 | @@ -178,9 +183,13 @@ __parse_one_specmb (const UCHAR_T *forma | |
159 | } | |
160 | } | |
161 | else if (ISDIGIT (*format)) | |
162 | - /* Constant width specification. */ | |
163 | - spec->info.width = read_int (&format); | |
164 | + { | |
165 | + int n = read_int (&format); | |
166 | ||
167 | + /* Constant width specification. */ | |
168 | + if (n != -1) | |
169 | + spec->info.width = n; | |
170 | + } | |
171 | /* Get the precision. */ | |
172 | spec->prec_arg = -1; | |
173 | /* -1 means none given; 0 means explicit 0. */ | |
174 | @@ -197,10 +206,13 @@ __parse_one_specmb (const UCHAR_T *forma | |
175 | { | |
176 | n = read_int (&format); | |
177 | ||
178 | - if (n > 0 && *format == L_('$')) | |
179 | + if (n != 0 && *format == L_('$')) | |
180 | { | |
181 | - spec->prec_arg = n - 1; | |
182 | - *max_ref_arg = MAX (*max_ref_arg, n); | |
183 | + if (n != -1) | |
184 | + { | |
185 | + spec->prec_arg = n - 1; | |
186 | + *max_ref_arg = MAX (*max_ref_arg, n); | |
187 | + } | |
188 | ++format; | |
189 | } | |
190 | } | |
191 | @@ -214,7 +226,12 @@ __parse_one_specmb (const UCHAR_T *forma | |
192 | } | |
193 | } | |
194 | else if (ISDIGIT (*format)) | |
195 | - spec->info.prec = read_int (&format); | |
196 | + { | |
197 | + int n = read_int (&format); | |
198 | + | |
199 | + if (n != -1) | |
200 | + spec->info.prec = n; | |
201 | + } | |
202 | else | |
203 | /* "%.?" is treated like "%.0?". */ | |
204 | spec->info.prec = 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, | |
211 | - &spec->size)) < 0) | |
212 | + || (int) (spec->ndata_args = (*__printf_arginfo_table[spec->info.spec]) | |
213 | + (&spec->info, 1, &spec->data_arg_type, | |
214 | + &spec->size)) < 0) | |
215 | { | |
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 | |
221 | @@ -1,4 +1,4 @@ | |
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. | |
225 | ||
226 | The GNU C Library is free software; you can redistribute it and/or | |
227 | @@ -12,9 +12,8 @@ | |
228 | Lesser General Public License for more details. | |
229 | ||
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 | |
233 | - 02111-1307 USA. */ | |
234 | + License along with the GNU C Library; if not, see | |
235 | + <http://www.gnu.org/licenses/>. */ | |
236 | ||
237 | #include <ctype.h> | |
238 | #include <limits.h> | |
239 | @@ -67,10 +66,10 @@ | |
240 | do { \ | |
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 \ | |
244 | - < _val, 0)) \ | |
245 | + if (__builtin_expect (INT_MAX - done < _val, 0)) \ | |
246 | { \ | |
247 | done = -1; \ | |
248 | + __set_errno (EOVERFLOW); \ | |
249 | goto all_done; \ | |
250 | } \ | |
251 | done += _val; \ | |
252 | @@ -141,12 +140,17 @@ | |
253 | do \ | |
254 | { \ | |
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)) \ | |
259 | { \ | |
260 | done = -1; \ | |
261 | goto all_done; \ | |
262 | } \ | |
263 | + if (__builtin_expect (INT_MAX - done < (Len), 0)) \ | |
264 | + { \ | |
265 | + done = -1; \ | |
266 | + __set_errno (EOVERFLOW); \ | |
267 | + goto all_done; \ | |
268 | + } \ | |
269 | done += (Len); \ | |
270 | } \ | |
271 | while (0) | |
272 | @@ -1435,10 +1439,21 @@ vfprintf (FILE *s, const CHAR_T *format, | |
273 | const UCHAR_T *tmp; /* Temporary value. */ | |
274 | ||
275 | tmp = ++f; | |
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)) | |
280 | + { | |
281 | + int pos = read_int (&tmp); | |
282 | ||
283 | + if (pos == -1) | |
284 | + { | |
285 | + __set_errno (EOVERFLOW); | |
286 | + done = -1; | |
287 | + goto all_done; | |
288 | + } | |
289 | + | |
290 | + if (pos && *tmp == L_('$')) | |
291 | + /* The width comes from a positional parameter. */ | |
292 | + goto do_positional; | |
293 | + } | |
294 | width = va_arg (ap, int); | |
295 | ||
296 | /* Negative width means left justified. */ | |
297 | @@ -1449,9 +1464,9 @@ vfprintf (FILE *s, const CHAR_T *format, | |
298 | left = 1; | |
299 | } | |
300 | ||
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)) | |
303 | { | |
304 | - __set_errno (ERANGE); | |
305 | + __set_errno (EOVERFLOW); | |
306 | done = -1; | |
307 | goto all_done; | |
308 | } | |
309 | @@ -1481,9 +1496,10 @@ vfprintf (FILE *s, const CHAR_T *format, | |
310 | LABEL (width): | |
311 | width = read_int (&f); | |
312 | ||
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)) | |
316 | { | |
317 | - __set_errno (ERANGE); | |
318 | + __set_errno (EOVERFLOW); | |
319 | done = -1; | |
320 | goto all_done; | |
321 | } | |
322 | @@ -1518,10 +1534,21 @@ vfprintf (FILE *s, const CHAR_T *format, | |
323 | const UCHAR_T *tmp; /* Temporary value. */ | |
324 | ||
325 | tmp = ++f; | |
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)) | |
330 | + { | |
331 | + int pos = read_int (&tmp); | |
332 | + | |
333 | + if (pos == -1) | |
334 | + { | |
335 | + __set_errno (EOVERFLOW); | |
336 | + done = -1; | |
337 | + goto all_done; | |
338 | + } | |
339 | ||
340 | + if (pos && *tmp == L_('$')) | |
341 | + /* The precision comes from a positional parameter. */ | |
342 | + goto do_positional; | |
343 | + } | |
344 | prec = va_arg (ap, int); | |
345 | ||
346 | /* If the precision is negative the precision is omitted. */ | |
347 | @@ -1529,15 +1556,26 @@ vfprintf (FILE *s, const CHAR_T *format, | |
348 | prec = -1; | |
349 | } | |
350 | else if (ISDIGIT (*f)) | |
351 | - prec = read_int (&f); | |
352 | + { | |
353 | + prec = read_int (&f); | |
354 | + | |
355 | + /* The precision was specified in this case as an extremely | |
356 | + large positive value. */ | |
357 | + if (prec == -1) | |
358 | + { | |
359 | + __set_errno (EOVERFLOW); | |
360 | + done = -1; | |
361 | + goto all_done; | |
362 | + } | |
363 | + } | |
364 | else | |
365 | prec = 0; | |
366 | if (prec > width | |
367 | && prec > sizeof (work_buffer) / sizeof (work_buffer[0]) - 32) | |
368 | { | |
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)) | |
371 | { | |
372 | - __set_errno (ERANGE); | |
373 | + __set_errno (EOVERFLOW); | |
374 | done = -1; | |
375 | goto all_done; | |
376 | } | |
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)); | |
385 | ||
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)) | |
389 | { | |
390 | - __set_errno (ERANGE); | |
391 | + __set_errno (EOVERFLOW); | |
392 | done = -1; | |
393 | goto all_done; | |
394 | } | |
395 | @@ -1746,6 +1784,8 @@ do_positional: | |
396 | } | |
397 | } | |
398 | ||
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', |