1 commit da1f431963218999c49cae928309dfec426c575c
2 Author: Joseph Myers <joseph@codesourcery.com>
3 Date: Mon Aug 27 15:59:24 2012 +0000
5 Fix strtod integer/buffer overflow (bug 14459).
6 (cherry picked from commit d6e70f4368533224e66d10b7f2126b899a3fd5e4)
14 diff --git a/stdlib/Makefile b/stdlib/Makefile
15 index f7811c5..79c9acb 100644
18 @@ -68,7 +68,8 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
19 tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 tst-rand48-2 \
20 tst-makecontext tst-strtod4 tst-strtod5 tst-qsort2 \
21 tst-makecontext2 tst-strtod6 tst-unsetenv1 \
22 - tst-makecontext3 bug-getcontext bug-fmtmsg1
23 + tst-makecontext3 bug-getcontext bug-fmtmsg1 \
28 diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c
29 index 2166a08..a8a7ea8 100644
30 --- a/stdlib/strtod_l.c
31 +++ b/stdlib/strtod_l.c
32 @@ -60,6 +60,7 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
38 /* The gmp headers need some configuration frobs. */
40 @@ -72,7 +73,6 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
42 #include "fpioconst.h"
48 @@ -174,19 +174,19 @@ extern const mp_limb_t _tens_in_limb[MAX_DIG_PER_LIMB + 1];
49 /* Return a floating point number of the needed type according to the given
50 multi-precision number after possible rounding. */
52 -round_and_return (mp_limb_t *retval, int exponent, int negative,
53 +round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
54 mp_limb_t round_limb, mp_size_t round_bit, int more_bits)
56 if (exponent < MIN_EXP - 1)
58 - mp_size_t shift = MIN_EXP - 1 - exponent;
60 - if (shift > MANT_DIG)
61 + if (exponent < MIN_EXP - 1 - MANT_DIG)
67 + mp_size_t shift = MIN_EXP - 1 - exponent;
69 more_bits |= (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0;
70 if (shift == MANT_DIG)
71 /* This is a special case to handle the very seldom case where
72 @@ -233,6 +233,9 @@ round_and_return (mp_limb_t *retval, int exponent, int negative,
76 + if (exponent > MAX_EXP)
79 if ((round_limb & (((mp_limb_t) 1) << round_bit)) != 0
80 && (more_bits || (retval[0] & 1) != 0
81 || (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0))
82 @@ -258,6 +261,7 @@ round_and_return (mp_limb_t *retval, int exponent, int negative,
85 if (exponent > MAX_EXP)
87 return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
89 return MPN2FLOAT (retval, exponent, negative);
90 @@ -271,7 +275,7 @@ round_and_return (mp_limb_t *retval, int exponent, int negative,
91 factor for the resulting number (see code) multiply by it. */
92 static const STRING_TYPE *
93 str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
97 , const char *decimal, size_t decimal_len, const char *thousands
99 @@ -301,6 +305,7 @@ str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
100 cy += __mpn_add_1 (n, n, *nsize, low);
103 + assert (*nsize < MPNSIZE);
107 @@ -335,7 +340,7 @@ str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
109 while (--digcnt > 0);
111 - if (*exponent > 0 && cnt + *exponent <= MAX_DIG_PER_LIMB)
112 + if (*exponent > 0 && *exponent <= MAX_DIG_PER_LIMB - cnt)
114 low *= _tens_in_limb[*exponent];
115 start = _tens_in_limb[cnt + *exponent];
116 @@ -355,7 +360,10 @@ str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
117 cy = __mpn_mul_1 (n, n, *nsize, start);
118 cy += __mpn_add_1 (n, n, *nsize, low);
120 - n[(*nsize)++] = cy;
122 + assert (*nsize < MPNSIZE);
123 + n[(*nsize)++] = cy;
128 @@ -413,7 +421,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
130 int negative; /* The sign of the number. */
131 MPN_VAR (num); /* MP representation of the number. */
132 - int exponent; /* Exponent of the number. */
133 + intmax_t exponent; /* Exponent of the number. */
135 /* Numbers starting `0X' or `0x' have to be processed with base 16. */
137 @@ -435,7 +443,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
138 /* Points at the character following the integer and fractional digits. */
139 const STRING_TYPE *expp;
140 /* Total number of digit and number of digits in integer part. */
141 - int dig_no, int_no, lead_zero;
142 + size_t dig_no, int_no, lead_zero;
143 /* Contains the last character read. */
146 @@ -767,7 +775,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
147 are all or any is really a fractional digit will be decided
150 - lead_zero = int_no == 0 ? -1 : 0;
151 + lead_zero = int_no == 0 ? (size_t) -1 : 0;
153 /* Read the fractional digits. A special case are the 'american
154 style' numbers like `16.' i.e. with decimal point but without
155 @@ -789,12 +797,13 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
156 (base == 16 && ({ CHAR_TYPE lo = TOLOWER (c);
157 lo >= L_('a') && lo <= L_('f'); })))
159 - if (c != L_('0') && lead_zero == -1)
160 + if (c != L_('0') && lead_zero == (size_t) -1)
161 lead_zero = dig_no - int_no;
166 + assert (dig_no <= (uintmax_t) INTMAX_MAX);
168 /* Remember start of exponent (if any). */
170 @@ -817,24 +826,80 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
172 if (c >= L_('0') && c <= L_('9'))
175 + intmax_t exp_limit;
177 /* Get the exponent limit. */
179 - exp_limit = (exp_negative ?
180 - -MIN_EXP + MANT_DIG + 4 * int_no :
181 - MAX_EXP - 4 * int_no + 4 * lead_zero + 3);
185 + assert (int_no <= (uintmax_t) (INTMAX_MAX
186 + + MIN_EXP - MANT_DIG) / 4);
187 + exp_limit = -MIN_EXP + MANT_DIG + 4 * (intmax_t) int_no;
193 + assert (lead_zero == 0
194 + && int_no <= (uintmax_t) INTMAX_MAX / 4);
195 + exp_limit = MAX_EXP - 4 * (intmax_t) int_no + 3;
197 + else if (lead_zero == (size_t) -1)
199 + /* The number is zero and this limit is
201 + exp_limit = MAX_EXP + 3;
206 + <= (uintmax_t) (INTMAX_MAX - MAX_EXP - 3) / 4);
207 + exp_limit = (MAX_EXP
208 + + 4 * (intmax_t) lead_zero
214 - exp_limit = (exp_negative ?
215 - -MIN_10_EXP + MANT_DIG + int_no :
216 - MAX_10_EXP - int_no + lead_zero + 1);
221 + <= (uintmax_t) (INTMAX_MAX + MIN_10_EXP - MANT_DIG));
222 + exp_limit = -MIN_10_EXP + MANT_DIG + (intmax_t) int_no;
228 + assert (lead_zero == 0
229 + && int_no <= (uintmax_t) INTMAX_MAX);
230 + exp_limit = MAX_10_EXP - (intmax_t) int_no + 1;
232 + else if (lead_zero == (size_t) -1)
234 + /* The number is zero and this limit is
236 + exp_limit = MAX_10_EXP + 1;
241 + <= (uintmax_t) (INTMAX_MAX - MAX_10_EXP - 1));
242 + exp_limit = MAX_10_EXP + (intmax_t) lead_zero + 1;
253 - exponent += c - L_('0');
255 - if (__builtin_expect (exponent > exp_limit, 0))
256 + if (__builtin_expect ((exponent > exp_limit / 10
257 + || (exponent == exp_limit / 10
258 + && c - L_('0') > exp_limit % 10)), 0))
259 /* The exponent is too large/small to represent a valid
262 @@ -843,7 +908,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
263 /* We have to take care for special situation: a joker
264 might have written "0.0e100000" which is in fact
266 - if (lead_zero == -1)
267 + if (lead_zero == (size_t) -1)
268 result = negative ? -0.0 : 0.0;
271 @@ -862,6 +927,9 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
276 + exponent += c - L_('0');
280 while (c >= L_('0') && c <= L_('9'));
281 @@ -930,7 +998,14 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
284 startp += lead_zero + decimal_len;
285 - exponent -= base == 16 ? 4 * lead_zero : lead_zero;
286 + assert (lead_zero <= (base == 16
287 + ? (uintmax_t) INTMAX_MAX / 4
288 + : (uintmax_t) INTMAX_MAX));
289 + assert (lead_zero <= (base == 16
290 + ? ((uintmax_t) exponent
291 + - (uintmax_t) INTMAX_MIN) / 4
292 + : ((uintmax_t) exponent - (uintmax_t) INTMAX_MIN)));
293 + exponent -= base == 16 ? 4 * (intmax_t) lead_zero : (intmax_t) lead_zero;
297 @@ -972,7 +1047,10 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
300 /* Adjust the exponent for the bits we are shifting in. */
301 - exponent += bits - 1 + (int_no - 1) * 4;
302 + assert (int_no <= (uintmax_t) (exponent < 0
303 + ? (INTMAX_MAX - bits + 1) / 4
304 + : (INTMAX_MAX - exponent - bits + 1) / 4));
305 + exponent += bits - 1 + ((intmax_t) int_no - 1) * 4;
307 while (--dig_no > 0 && idx >= 0)
309 @@ -1024,13 +1102,15 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
310 really integer digits or belong to the fractional part; i.e. we normalize
313 - register int incr = (exponent < 0 ? MAX (-int_no, exponent)
314 - : MIN (dig_no - int_no, exponent));
315 + register intmax_t incr = (exponent < 0
316 + ? MAX (-(intmax_t) int_no, exponent)
317 + : MIN ((intmax_t) dig_no - (intmax_t) int_no,
323 - if (__builtin_expect (int_no + exponent > MAX_10_EXP + 1, 0))
324 + if (__builtin_expect (exponent > MAX_10_EXP + 1 - (intmax_t) int_no, 0))
326 __set_errno (ERANGE);
327 return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
328 @@ -1215,7 +1295,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
329 digits we should have enough bits for the result. The remaining
330 decimal digits give us the information that more bits are following.
331 This can be used while rounding. (Two added as a safety margin.) */
332 - if (dig_no - int_no > (MANT_DIG - bits + 2) / 3 + 2)
333 + if ((intmax_t) dig_no > (intmax_t) int_no + (MANT_DIG - bits + 2) / 3 + 2)
335 dig_no = int_no + (MANT_DIG - bits + 2) / 3 + 2;
337 @@ -1223,7 +1303,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
341 - neg_exp = dig_no - int_no - exponent;
342 + neg_exp = (intmax_t) dig_no - (intmax_t) int_no - exponent;
344 /* Construct the denominator. */
346 diff --git a/stdlib/tst-strtod-overflow.c b/stdlib/tst-strtod-overflow.c
348 index 0000000..668d55b
350 +++ b/stdlib/tst-strtod-overflow.c
352 +/* Test for integer/buffer overflow in strtod.
353 + Copyright (C) 2012 Free Software Foundation, Inc.
354 + This file is part of the GNU C Library.
356 + The GNU C Library is free software; you can redistribute it and/or
357 + modify it under the terms of the GNU Lesser General Public
358 + License as published by the Free Software Foundation; either
359 + version 2.1 of the License, or (at your option) any later version.
361 + The GNU C Library is distributed in the hope that it will be useful,
362 + but WITHOUT ANY WARRANTY; without even the implied warranty of
363 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
364 + Lesser General Public License for more details.
366 + You should have received a copy of the GNU Lesser General Public
367 + License along with the GNU C Library; if not, see
368 + <http://www.gnu.org/licenses/>. */
374 +#define EXPONENT "e-2147483649"
375 +#define SIZE 214748364
380 + char *p = malloc (1 + SIZE + sizeof (EXPONENT));
383 + puts ("malloc failed, cannot test for overflow");
387 + memset (p + 1, '0', SIZE);
388 + memcpy (p + 1 + SIZE, EXPONENT, sizeof (EXPONENT));
389 + double d = strtod (p, NULL);
392 + printf ("strtod returned wrong value: %a\n", d);
398 +#define TEST_FUNCTION do_test ()
399 +#include "../test-skeleton.c"