]>
Commit | Line | Data |
---|---|---|
30a4e827 MT |
1 | diff -Nrup a/stdlib/Makefile b/stdlib/Makefile |
2 | --- a/stdlib/Makefile 2010-05-04 05:27:23.000000000 -0600 | |
3 | +++ b/stdlib/Makefile 2012-08-15 09:25:37.812443006 -0600 | |
4 | @@ -71,7 +71,7 @@ tests := tst-strtol tst-strtod testmb t | |
5 | tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 tst-rand48-2 \ | |
6 | tst-makecontext tst-strtod4 tst-strtod5 tst-qsort2 \ | |
7 | tst-makecontext2 tst-strtod6 tst-unsetenv1 \ | |
8 | - tst-makecontext3 | |
9 | + tst-makecontext3 tst-strtod-overflow | |
10 | ||
11 | include ../Makeconfig | |
12 | ||
13 | diff -Nrup a/stdlib/strtod_l.c b/stdlib/strtod_l.c | |
14 | --- a/stdlib/strtod_l.c 2010-05-04 05:27:23.000000000 -0600 | |
15 | +++ b/stdlib/strtod_l.c 2012-08-15 09:34:29.550281346 -0600 | |
16 | @@ -62,6 +62,7 @@ extern unsigned long long int ____strtou | |
17 | #include <math.h> | |
18 | #include <stdlib.h> | |
19 | #include <string.h> | |
20 | +#include <stdint.h> | |
21 | ||
22 | /* The gmp headers need some configuration frobs. */ | |
23 | #define HAVE_ALLOCA 1 | |
24 | @@ -176,19 +177,19 @@ extern const mp_limb_t _tens_in_limb[MAX | |
25 | /* Return a floating point number of the needed type according to the given | |
26 | multi-precision number after possible rounding. */ | |
27 | static FLOAT | |
28 | -round_and_return (mp_limb_t *retval, int exponent, int negative, | |
29 | +round_and_return (mp_limb_t *retval, intmax_t exponent, int negative, | |
30 | mp_limb_t round_limb, mp_size_t round_bit, int more_bits) | |
31 | { | |
32 | if (exponent < MIN_EXP - 1) | |
33 | { | |
34 | - mp_size_t shift = MIN_EXP - 1 - exponent; | |
35 | - | |
36 | - if (shift > MANT_DIG) | |
37 | + if (exponent < MIN_EXP - 1 - MANT_DIG) | |
38 | { | |
39 | __set_errno (EDOM); | |
40 | return 0.0; | |
41 | } | |
42 | ||
43 | + mp_size_t shift = MIN_EXP - 1 - exponent; | |
44 | + | |
45 | more_bits |= (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0; | |
46 | if (shift == MANT_DIG) | |
47 | /* This is a special case to handle the very seldom case where | |
48 | @@ -235,6 +236,9 @@ round_and_return (mp_limb_t *retval, int | |
49 | __set_errno (ERANGE); | |
50 | } | |
51 | ||
52 | + if (exponent > MAX_EXP) | |
53 | + goto overflow; | |
54 | + | |
55 | if ((round_limb & (((mp_limb_t) 1) << round_bit)) != 0 | |
56 | && (more_bits || (retval[0] & 1) != 0 | |
57 | || (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0)) | |
58 | @@ -260,6 +264,7 @@ round_and_return (mp_limb_t *retval, int | |
59 | } | |
60 | ||
61 | if (exponent > MAX_EXP) | |
62 | + overflow: | |
63 | return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; | |
64 | ||
65 | return MPN2FLOAT (retval, exponent, negative); | |
66 | @@ -273,7 +278,7 @@ round_and_return (mp_limb_t *retval, int | |
67 | factor for the resulting number (see code) multiply by it. */ | |
68 | static const STRING_TYPE * | |
69 | str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize, | |
70 | - int *exponent | |
71 | + intmax_t *exponent | |
72 | #ifndef USE_WIDE_CHAR | |
73 | , const char *decimal, size_t decimal_len, const char *thousands | |
74 | #endif | |
75 | @@ -337,7 +342,7 @@ str_to_mpn (const STRING_TYPE *str, int | |
76 | } | |
77 | while (--digcnt > 0); | |
78 | ||
79 | - if (*exponent > 0 && cnt + *exponent <= MAX_DIG_PER_LIMB) | |
80 | + if (*exponent > 0 && *exponent <= MAX_DIG_PER_LIMB - cnt) | |
81 | { | |
82 | low *= _tens_in_limb[*exponent]; | |
83 | start = _tens_in_limb[cnt + *exponent]; | |
84 | @@ -415,7 +420,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group | |
85 | { | |
86 | int negative; /* The sign of the number. */ | |
87 | MPN_VAR (num); /* MP representation of the number. */ | |
88 | - int exponent; /* Exponent of the number. */ | |
89 | + intmax_t exponent; /* Exponent of the number. */ | |
90 | ||
91 | /* Numbers starting `0X' or `0x' have to be processed with base 16. */ | |
92 | int base = 10; | |
93 | @@ -437,7 +442,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group | |
94 | /* Points at the character following the integer and fractional digits. */ | |
95 | const STRING_TYPE *expp; | |
96 | /* Total number of digit and number of digits in integer part. */ | |
97 | - int dig_no, int_no, lead_zero; | |
98 | + size_t dig_no, int_no, lead_zero; | |
99 | /* Contains the last character read. */ | |
100 | CHAR_TYPE c; | |
101 | ||
102 | @@ -769,7 +774,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group | |
103 | are all or any is really a fractional digit will be decided | |
104 | later. */ | |
105 | int_no = dig_no; | |
106 | - lead_zero = int_no == 0 ? -1 : 0; | |
107 | + lead_zero = int_no == 0 ? (size_t) -1 : 0; | |
108 | ||
109 | /* Read the fractional digits. A special case are the 'american | |
110 | style' numbers like `16.' i.e. with decimal point but without | |
111 | @@ -791,12 +796,13 @@ ____STRTOF_INTERNAL (nptr, endptr, group | |
112 | (base == 16 && ({ CHAR_TYPE lo = TOLOWER (c); | |
113 | lo >= L_('a') && lo <= L_('f'); }))) | |
114 | { | |
115 | - if (c != L_('0') && lead_zero == -1) | |
116 | + if (c != L_('0') && lead_zero == (size_t) -1) | |
117 | lead_zero = dig_no - int_no; | |
118 | ++dig_no; | |
119 | c = *++cp; | |
120 | } | |
121 | } | |
122 | + assert (dig_no <= (uintmax_t) INTMAX_MAX); | |
123 | ||
124 | /* Remember start of exponent (if any). */ | |
125 | expp = cp; | |
126 | @@ -819,24 +825,80 @@ ____STRTOF_INTERNAL (nptr, endptr, group | |
127 | ||
128 | if (c >= L_('0') && c <= L_('9')) | |
129 | { | |
130 | - int exp_limit; | |
131 | + intmax_t exp_limit; | |
132 | ||
133 | /* Get the exponent limit. */ | |
134 | if (base == 16) | |
135 | - exp_limit = (exp_negative ? | |
136 | - -MIN_EXP + MANT_DIG + 4 * int_no : | |
137 | - MAX_EXP - 4 * int_no + 4 * lead_zero + 3); | |
138 | + { | |
139 | + if (exp_negative) | |
140 | + { | |
141 | + assert (int_no <= (uintmax_t) (INTMAX_MAX | |
142 | + + MIN_EXP - MANT_DIG) / 4); | |
143 | + exp_limit = -MIN_EXP + MANT_DIG + 4 * (intmax_t) int_no; | |
144 | + } | |
145 | + else | |
146 | + { | |
147 | + if (int_no) | |
148 | + { | |
149 | + assert (lead_zero == 0 | |
150 | + && int_no <= (uintmax_t) INTMAX_MAX / 4); | |
151 | + exp_limit = MAX_EXP - 4 * (intmax_t) int_no + 3; | |
152 | + } | |
153 | + else if (lead_zero == (size_t) -1) | |
154 | + { | |
155 | + /* The number is zero and this limit is | |
156 | + arbitrary. */ | |
157 | + exp_limit = MAX_EXP + 3; | |
158 | + } | |
159 | + else | |
160 | + { | |
161 | + assert (lead_zero | |
162 | + <= (uintmax_t) (INTMAX_MAX - MAX_EXP - 3) / 4); | |
163 | + exp_limit = (MAX_EXP | |
164 | + + 4 * (intmax_t) lead_zero | |
165 | + + 3); | |
166 | + } | |
167 | + } | |
168 | + } | |
169 | else | |
170 | - exp_limit = (exp_negative ? | |
171 | - -MIN_10_EXP + MANT_DIG + int_no : | |
172 | - MAX_10_EXP - int_no + lead_zero + 1); | |
173 | + { | |
174 | + if (exp_negative) | |
175 | + { | |
176 | + assert (int_no | |
177 | + <= (uintmax_t) (INTMAX_MAX + MIN_10_EXP - MANT_DIG)); | |
178 | + exp_limit = -MIN_10_EXP + MANT_DIG + (intmax_t) int_no; | |
179 | + } | |
180 | + else | |
181 | + { | |
182 | + if (int_no) | |
183 | + { | |
184 | + assert (lead_zero == 0 | |
185 | + && int_no <= (uintmax_t) INTMAX_MAX); | |
186 | + exp_limit = MAX_10_EXP - (intmax_t) int_no + 1; | |
187 | + } | |
188 | + else if (lead_zero == (size_t) -1) | |
189 | + { | |
190 | + /* The number is zero and this limit is | |
191 | + arbitrary. */ | |
192 | + exp_limit = MAX_10_EXP + 1; | |
193 | + } | |
194 | + else | |
195 | + { | |
196 | + assert (lead_zero | |
197 | + <= (uintmax_t) (INTMAX_MAX - MAX_10_EXP - 1)); | |
198 | + exp_limit = MAX_10_EXP + (intmax_t) lead_zero + 1; | |
199 | + } | |
200 | + } | |
201 | + } | |
202 | + | |
203 | + if (exp_limit < 0) | |
204 | + exp_limit = 0; | |
205 | ||
206 | do | |
207 | { | |
208 | - exponent *= 10; | |
209 | - exponent += c - L_('0'); | |
210 | - | |
211 | - if (__builtin_expect (exponent > exp_limit, 0)) | |
212 | + if (__builtin_expect ((exponent > exp_limit / 10 | |
213 | + || (exponent == exp_limit / 10 | |
214 | + && c - L_('0') > exp_limit % 10)), 0)) | |
215 | /* The exponent is too large/small to represent a valid | |
216 | number. */ | |
217 | { | |
218 | @@ -845,7 +907,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group | |
219 | /* We have to take care for special situation: a joker | |
220 | might have written "0.0e100000" which is in fact | |
221 | zero. */ | |
222 | - if (lead_zero == -1) | |
223 | + if (lead_zero == (size_t) -1) | |
224 | result = negative ? -0.0 : 0.0; | |
225 | else | |
226 | { | |
227 | @@ -864,6 +926,9 @@ ____STRTOF_INTERNAL (nptr, endptr, group | |
228 | /* NOTREACHED */ | |
229 | } | |
230 | ||
231 | + exponent *= 10; | |
232 | + exponent += c - L_('0'); | |
233 | + | |
234 | c = *++cp; | |
235 | } | |
236 | while (c >= L_('0') && c <= L_('9')); | |
237 | @@ -932,7 +997,14 @@ ____STRTOF_INTERNAL (nptr, endptr, group | |
238 | } | |
239 | #endif | |
240 | startp += lead_zero + decimal_len; | |
241 | - exponent -= base == 16 ? 4 * lead_zero : lead_zero; | |
242 | + assert (lead_zero <= (base == 16 | |
243 | + ? (uintmax_t) INTMAX_MAX / 4 | |
244 | + : (uintmax_t) INTMAX_MAX)); | |
245 | + assert (lead_zero <= (base == 16 | |
246 | + ? ((uintmax_t) exponent | |
247 | + - (uintmax_t) INTMAX_MIN) / 4 | |
248 | + : ((uintmax_t) exponent - (uintmax_t) INTMAX_MIN))); | |
249 | + exponent -= base == 16 ? 4 * (intmax_t) lead_zero : (intmax_t) lead_zero; | |
250 | dig_no -= lead_zero; | |
251 | } | |
252 | ||
253 | @@ -974,7 +1046,10 @@ ____STRTOF_INTERNAL (nptr, endptr, group | |
254 | } | |
255 | ||
256 | /* Adjust the exponent for the bits we are shifting in. */ | |
257 | - exponent += bits - 1 + (int_no - 1) * 4; | |
258 | + assert (int_no <= (uintmax_t) (exponent < 0 | |
259 | + ? (INTMAX_MAX - bits + 1) / 4 | |
260 | + : (INTMAX_MAX - exponent - bits + 1) / 4)); | |
261 | + exponent += bits - 1 + ((intmax_t) int_no - 1) * 4; | |
262 | ||
263 | while (--dig_no > 0 && idx >= 0) | |
264 | { | |
265 | @@ -1014,13 +1089,15 @@ ____STRTOF_INTERNAL (nptr, endptr, group | |
266 | really integer digits or belong to the fractional part; i.e. we normalize | |
267 | 123e-2 to 1.23. */ | |
268 | { | |
269 | - register int incr = (exponent < 0 ? MAX (-int_no, exponent) | |
270 | - : MIN (dig_no - int_no, exponent)); | |
271 | + register intmax_t incr = (exponent < 0 | |
272 | + ? MAX (-(intmax_t) int_no, exponent) | |
273 | + : MIN ((intmax_t) dig_no - (intmax_t) int_no, | |
274 | + exponent)); | |
275 | int_no += incr; | |
276 | exponent -= incr; | |
277 | } | |
278 | ||
279 | - if (__builtin_expect (int_no + exponent > MAX_10_EXP + 1, 0)) | |
280 | + if (__builtin_expect (exponent > MAX_10_EXP + 1 - (intmax_t) int_no, 0)) | |
281 | { | |
282 | __set_errno (ERANGE); | |
283 | return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; | |
284 | @@ -1205,7 +1282,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group | |
285 | digits we should have enough bits for the result. The remaining | |
286 | decimal digits give us the information that more bits are following. | |
287 | This can be used while rounding. (Two added as a safety margin.) */ | |
288 | - if (dig_no - int_no > (MANT_DIG - bits + 2) / 3 + 2) | |
289 | + if ((intmax_t) dig_no > (intmax_t) int_no + (MANT_DIG - bits + 2) / 3 + 2) | |
290 | { | |
291 | dig_no = int_no + (MANT_DIG - bits + 2) / 3 + 2; | |
292 | more_bits = 1; | |
293 | @@ -1213,7 +1290,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group | |
294 | else | |
295 | more_bits = 0; | |
296 | ||
297 | - neg_exp = dig_no - int_no - exponent; | |
298 | + neg_exp = (intmax_t) dig_no - (intmax_t) int_no - exponent; | |
299 | ||
300 | /* Construct the denominator. */ | |
301 | densize = 0; | |
302 | @@ -1491,7 +1568,9 @@ ____STRTOF_INTERNAL (nptr, endptr, group | |
303 | register int i; | |
304 | (void) __mpn_lshift (&retval[used | |
305 | / BITS_PER_MP_LIMB], | |
306 | - retval, RETURN_LIMB_SIZE, | |
307 | + retval, | |
308 | + (RETURN_LIMB_SIZE | |
309 | + - used / BITS_PER_MP_LIMB), | |
310 | used % BITS_PER_MP_LIMB); | |
311 | for (i = used / BITS_PER_MP_LIMB - 1; i >= 0; --i) | |
312 | retval[i] = 0; | |
313 | diff -Nrup a/stdlib/tst-strtod-overflow.c b/stdlib/tst-strtod-overflow.c | |
314 | --- a/stdlib/tst-strtod-overflow.c 1969-12-31 17:00:00.000000000 -0700 | |
315 | +++ b/stdlib/tst-strtod-overflow.c 2012-08-15 09:25:01.098592764 -0600 | |
316 | @@ -0,0 +1,48 @@ | |
317 | +/* Test for integer/buffer overflow in strtod. | |
318 | + Copyright (C) 2012 Free Software Foundation, Inc. | |
319 | + This file is part of the GNU C Library. | |
320 | + | |
321 | + The GNU C Library is free software; you can redistribute it and/or | |
322 | + modify it under the terms of the GNU Lesser General Public | |
323 | + License as published by the Free Software Foundation; either | |
324 | + version 2.1 of the License, or (at your option) any later version. | |
325 | + | |
326 | + The GNU C Library is distributed in the hope that it will be useful, | |
327 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
328 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
329 | + Lesser General Public License for more details. | |
330 | + | |
331 | + You should have received a copy of the GNU Lesser General Public | |
332 | + License along with the GNU C Library; if not, see | |
333 | + <http://www.gnu.org/licenses/>. */ | |
334 | + | |
335 | +#include <stdio.h> | |
336 | +#include <stdlib.h> | |
337 | +#include <string.h> | |
338 | + | |
339 | +#define EXPONENT "e-2147483649" | |
340 | +#define SIZE 214748364 | |
341 | + | |
342 | +static int | |
343 | +do_test (void) | |
344 | +{ | |
345 | + char *p = malloc (1 + SIZE + sizeof (EXPONENT)); | |
346 | + if (p == NULL) | |
347 | + { | |
348 | + puts ("malloc failed, cannot test for overflow"); | |
349 | + return 0; | |
350 | + } | |
351 | + p[0] = '1'; | |
352 | + memset (p + 1, '0', SIZE); | |
353 | + memcpy (p + 1 + SIZE, EXPONENT, sizeof (EXPONENT)); | |
354 | + double d = strtod (p, NULL); | |
355 | + if (d != 0) | |
356 | + { | |
357 | + printf ("strtod returned wrong value: %a\n", d); | |
358 | + return 1; | |
359 | + } | |
360 | + return 0; | |
361 | +} | |
362 | + | |
363 | +#define TEST_FUNCTION do_test () | |
364 | +#include "../test-skeleton.c" |