CRUX-ARM : Home

Home :: Documentation :: Download :: Development :: Community :: Ports :: Packages :: Bugs :: Links :: About :: Donors
glibc: aligned kernel headers to upstream version 3.4.11
[crossrootfs.git] / glibc / glibc-strtod_integer_overflow.patch
CommitLineData
eba82382
VM
1commit da1f431963218999c49cae928309dfec426c575c
2Author: Joseph Myers <joseph@codesourcery.com>
3Date: Mon Aug 27 15:59:24 2012 +0000
4
5 Fix strtod integer/buffer overflow (bug 14459).
6 (cherry picked from commit d6e70f4368533224e66d10b7f2126b899a3fd5e4)
7
8 Conflicts:
9
10 ChangeLog
11 NEWS
12 stdlib/Makefile
13
14diff --git a/stdlib/Makefile b/stdlib/Makefile
15index f7811c5..79c9acb 100644
16--- a/stdlib/Makefile
17+++ b/stdlib/Makefile
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 \
24+ tst-strtod-overflow
25
26 include ../Makeconfig
27
28diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c
29index 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 **,
33 #include <math.h>
34 #include <stdlib.h>
35 #include <string.h>
36+#include <stdint.h>
37
38 /* The gmp headers need some configuration frobs. */
39 #define HAVE_ALLOCA 1
40@@ -72,7 +73,6 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
41 #include "longlong.h"
42 #include "fpioconst.h"
43
44-#define NDEBUG 1
45 #include <assert.h>
46
47
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. */
51 static FLOAT
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)
55 {
56 if (exponent < MIN_EXP - 1)
57 {
58- mp_size_t shift = MIN_EXP - 1 - exponent;
59-
60- if (shift > MANT_DIG)
61+ if (exponent < MIN_EXP - 1 - MANT_DIG)
62 {
63 __set_errno (ERANGE);
64 return 0.0;
65 }
66
67+ mp_size_t shift = MIN_EXP - 1 - exponent;
68+
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,
73 __set_errno (ERANGE);
74 }
75
76+ if (exponent > MAX_EXP)
77+ goto overflow;
78+
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,
83 }
84
85 if (exponent > MAX_EXP)
86+ overflow:
87 return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
88
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,
94- int *exponent
95+ intmax_t *exponent
96 #ifndef USE_WIDE_CHAR
97 , const char *decimal, size_t decimal_len, const char *thousands
98 #endif
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);
101 if (cy != 0)
102 {
103+ assert (*nsize < MPNSIZE);
104 n[*nsize] = cy;
105 ++(*nsize);
106 }
107@@ -335,7 +340,7 @@ str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
108 }
109 while (--digcnt > 0);
110
111- if (*exponent > 0 && cnt + *exponent <= MAX_DIG_PER_LIMB)
112+ if (*exponent > 0 && *exponent <= MAX_DIG_PER_LIMB - cnt)
113 {
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);
119 if (cy != 0)
120- n[(*nsize)++] = cy;
121+ {
122+ assert (*nsize < MPNSIZE);
123+ n[(*nsize)++] = cy;
124+ }
125 }
126
127 return str;
128@@ -413,7 +421,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
129 {
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. */
134
135 /* Numbers starting `0X' or `0x' have to be processed with base 16. */
136 int base = 10;
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. */
144 CHAR_TYPE c;
145
146@@ -767,7 +775,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
147 are all or any is really a fractional digit will be decided
148 later. */
149 int_no = dig_no;
150- lead_zero = int_no == 0 ? -1 : 0;
151+ lead_zero = int_no == 0 ? (size_t) -1 : 0;
152
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'); })))
158 {
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;
162 ++dig_no;
163 c = *++cp;
164 }
165 }
166+ assert (dig_no <= (uintmax_t) INTMAX_MAX);
167
168 /* Remember start of exponent (if any). */
169 expp = cp;
170@@ -817,24 +826,80 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
171
172 if (c >= L_('0') && c <= L_('9'))
173 {
174- int exp_limit;
175+ intmax_t exp_limit;
176
177 /* Get the exponent limit. */
178 if (base == 16)
179- exp_limit = (exp_negative ?
180- -MIN_EXP + MANT_DIG + 4 * int_no :
181- MAX_EXP - 4 * int_no + 4 * lead_zero + 3);
182+ {
183+ if (exp_negative)
184+ {
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;
188+ }
189+ else
190+ {
191+ if (int_no)
192+ {
193+ assert (lead_zero == 0
194+ && int_no <= (uintmax_t) INTMAX_MAX / 4);
195+ exp_limit = MAX_EXP - 4 * (intmax_t) int_no + 3;
196+ }
197+ else if (lead_zero == (size_t) -1)
198+ {
199+ /* The number is zero and this limit is
200+ arbitrary. */
201+ exp_limit = MAX_EXP + 3;
202+ }
203+ else
204+ {
205+ assert (lead_zero
206+ <= (uintmax_t) (INTMAX_MAX - MAX_EXP - 3) / 4);
207+ exp_limit = (MAX_EXP
208+ + 4 * (intmax_t) lead_zero
209+ + 3);
210+ }
211+ }
212+ }
213 else
214- exp_limit = (exp_negative ?
215- -MIN_10_EXP + MANT_DIG + int_no :
216- MAX_10_EXP - int_no + lead_zero + 1);
217+ {
218+ if (exp_negative)
219+ {
220+ assert (int_no
221+ <= (uintmax_t) (INTMAX_MAX + MIN_10_EXP - MANT_DIG));
222+ exp_limit = -MIN_10_EXP + MANT_DIG + (intmax_t) int_no;
223+ }
224+ else
225+ {
226+ if (int_no)
227+ {
228+ assert (lead_zero == 0
229+ && int_no <= (uintmax_t) INTMAX_MAX);
230+ exp_limit = MAX_10_EXP - (intmax_t) int_no + 1;
231+ }
232+ else if (lead_zero == (size_t) -1)
233+ {
234+ /* The number is zero and this limit is
235+ arbitrary. */
236+ exp_limit = MAX_10_EXP + 1;
237+ }
238+ else
239+ {
240+ assert (lead_zero
241+ <= (uintmax_t) (INTMAX_MAX - MAX_10_EXP - 1));
242+ exp_limit = MAX_10_EXP + (intmax_t) lead_zero + 1;
243+ }
244+ }
245+ }
246+
247+ if (exp_limit < 0)
248+ exp_limit = 0;
249
250 do
251 {
252- exponent *= 10;
253- exponent += c - L_('0');
254-
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
260 number. */
261 {
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
265 zero. */
266- if (lead_zero == -1)
267+ if (lead_zero == (size_t) -1)
268 result = negative ? -0.0 : 0.0;
269 else
270 {
271@@ -862,6 +927,9 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
272 /* NOTREACHED */
273 }
274
275+ exponent *= 10;
276+ exponent += c - L_('0');
277+
278 c = *++cp;
279 }
280 while (c >= L_('0') && c <= L_('9'));
281@@ -930,7 +998,14 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
282 }
283 #endif
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;
294 dig_no -= lead_zero;
295 }
296
297@@ -972,7 +1047,10 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
298 }
299
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;
306
307 while (--dig_no > 0 && idx >= 0)
308 {
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
311 123e-2 to 1.23. */
312 {
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,
318+ exponent));
319 int_no += incr;
320 exponent -= incr;
321 }
322
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))
325 {
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)
334 {
335 dig_no = int_no + (MANT_DIG - bits + 2) / 3 + 2;
336 more_bits = 1;
337@@ -1223,7 +1303,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
338 else
339 more_bits = 0;
340
341- neg_exp = dig_no - int_no - exponent;
342+ neg_exp = (intmax_t) dig_no - (intmax_t) int_no - exponent;
343
344 /* Construct the denominator. */
345 densize = 0;
346diff --git a/stdlib/tst-strtod-overflow.c b/stdlib/tst-strtod-overflow.c
347new file mode 100644
348index 0000000..668d55b
349--- /dev/null
350+++ b/stdlib/tst-strtod-overflow.c
351@@ -0,0 +1,48 @@
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.
355+
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.
360+
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.
365+
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/>. */
369+
370+#include <stdio.h>
371+#include <stdlib.h>
372+#include <string.h>
373+
374+#define EXPONENT "e-2147483649"
375+#define SIZE 214748364
376+
377+static int
378+do_test (void)
379+{
380+ char *p = malloc (1 + SIZE + sizeof (EXPONENT));
381+ if (p == NULL)
382+ {
383+ puts ("malloc failed, cannot test for overflow");
384+ return 0;
385+ }
386+ p[0] = '1';
387+ memset (p + 1, '0', SIZE);
388+ memcpy (p + 1 + SIZE, EXPONENT, sizeof (EXPONENT));
389+ double d = strtod (p, NULL);
390+ if (d != 0)
391+ {
392+ printf ("strtod returned wrong value: %a\n", d);
393+ return 1;
394+ }
395+ return 0;
396+}
397+
398+#define TEST_FUNCTION do_test ()
399+#include "../test-skeleton.c"