Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Fix nan functions handling of payload strings (bug 16961, bug 16962).
The nan, nanf and nanl functions handle payload strings by doing e.g.: if (tagp[0] != '\0') { char buf[6 + strlen (tagp)]; sprintf (buf, "NAN(%s)", tagp); return strtod (buf, NULL); } This is an unbounded stack allocation based on the length of the argument. Furthermore, if the argument starts with an n-char-sequence followed by ')', that n-char-sequence is wrongly treated as significant for determining the payload of the resulting NaN, when ISO C says the call should be equivalent to strtod ("NAN", NULL), without being affected by that initial n-char-sequence. This patch fixes both those problems by using the __strtod_nan etc. functions recently factored out of strtod etc. for that purpose, with those functions being exported from libc at version GLIBC_PRIVATE. Tested for x86_64, x86, mips64 and powerpc. [BZ #16961] [BZ #16962] * math/s_nan.c (__nan): Use __strtod_nan instead of constructing a string on the stack for strtod. * math/s_nanf.c (__nanf): Use __strtof_nan instead of constructing a string on the stack for strtof. * math/s_nanl.c (__nanl): Use __strtold_nan instead of constructing a string on the stack for strtold. * stdlib/Versions (libc): Add __strtof_nan, __strtod_nan and __strtold_nan to GLIBC_PRIVATE. * math/test-nan-overflow.c: New file. * math/test-nan-payload.c: Likewise. * math/Makefile (tests): Add test-nan-overflow and test-nan-payload.
- Loading branch information
Joseph Myers
committed
Dec 4, 2015
1 parent
79e0d34
commit 8f5e8b0
Showing
9 changed files
with
217 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* Test nan functions stack overflow (bug 16962). | ||
Copyright (C) 2015 Free Software Foundation, Inc. | ||
This file is part of the GNU C Library. | ||
The GNU C Library is free software; you can redistribute it and/or | ||
modify it under the terms of the GNU Lesser General Public | ||
License as published by the Free Software Foundation; either | ||
version 2.1 of the License, or (at your option) any later version. | ||
The GNU C Library is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
Lesser General Public License for more details. | ||
You should have received a copy of the GNU Lesser General Public | ||
License along with the GNU C Library; if not, see | ||
<http://www.gnu.org/licenses/>. */ | ||
|
||
#include <math.h> | ||
#include <stdio.h> | ||
#include <string.h> | ||
#include <sys/resource.h> | ||
|
||
#define STACK_LIM 1048576 | ||
#define STRING_SIZE (2 * STACK_LIM) | ||
|
||
static int | ||
do_test (void) | ||
{ | ||
int result = 0; | ||
struct rlimit lim; | ||
getrlimit (RLIMIT_STACK, &lim); | ||
lim.rlim_cur = STACK_LIM; | ||
setrlimit (RLIMIT_STACK, &lim); | ||
char *nanstr = malloc (STRING_SIZE); | ||
if (nanstr == NULL) | ||
{ | ||
puts ("malloc failed, cannot test"); | ||
return 77; | ||
} | ||
memset (nanstr, '0', STRING_SIZE - 1); | ||
nanstr[STRING_SIZE - 1] = 0; | ||
#define NAN_TEST(TYPE, FUNC) \ | ||
do \ | ||
{ \ | ||
char *volatile p = nanstr; \ | ||
volatile TYPE v = FUNC (p); \ | ||
if (isnan (v)) \ | ||
puts ("PASS: " #FUNC); \ | ||
else \ | ||
{ \ | ||
puts ("FAIL: " #FUNC); \ | ||
result = 1; \ | ||
} \ | ||
} \ | ||
while (0) | ||
NAN_TEST (float, nanf); | ||
NAN_TEST (double, nan); | ||
#ifndef NO_LONG_DOUBLE | ||
NAN_TEST (long double, nanl); | ||
#endif | ||
return result; | ||
} | ||
|
||
#define TEST_FUNCTION do_test () | ||
#include "../test-skeleton.c" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
/* Test nan functions payload handling (bug 16961). | ||
Copyright (C) 2015 Free Software Foundation, Inc. | ||
This file is part of the GNU C Library. | ||
The GNU C Library is free software; you can redistribute it and/or | ||
modify it under the terms of the GNU Lesser General Public | ||
License as published by the Free Software Foundation; either | ||
version 2.1 of the License, or (at your option) any later version. | ||
The GNU C Library is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
Lesser General Public License for more details. | ||
You should have received a copy of the GNU Lesser General Public | ||
License along with the GNU C Library; if not, see | ||
<http://www.gnu.org/licenses/>. */ | ||
|
||
#include <float.h> | ||
#include <math.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
|
||
/* Avoid built-in functions. */ | ||
#define WRAP_NAN(FUNC, STR) \ | ||
({ const char *volatile wns = (STR); FUNC (wns); }) | ||
#define WRAP_STRTO(FUNC, STR) \ | ||
({ const char *volatile wss = (STR); FUNC (wss, NULL); }) | ||
|
||
#define CHECK_IS_NAN(TYPE, A) \ | ||
do \ | ||
{ \ | ||
if (isnan (A)) \ | ||
puts ("PASS: " #TYPE " " #A); \ | ||
else \ | ||
{ \ | ||
puts ("FAIL: " #TYPE " " #A); \ | ||
result = 1; \ | ||
} \ | ||
} \ | ||
while (0) | ||
|
||
#define CHECK_SAME_NAN(TYPE, A, B) \ | ||
do \ | ||
{ \ | ||
if (memcmp (&(A), &(B), sizeof (A)) == 0) \ | ||
puts ("PASS: " #TYPE " " #A " = " #B); \ | ||
else \ | ||
{ \ | ||
puts ("FAIL: " #TYPE " " #A " = " #B); \ | ||
result = 1; \ | ||
} \ | ||
} \ | ||
while (0) | ||
|
||
#define CHECK_DIFF_NAN(TYPE, A, B) \ | ||
do \ | ||
{ \ | ||
if (memcmp (&(A), &(B), sizeof (A)) != 0) \ | ||
puts ("PASS: " #TYPE " " #A " != " #B); \ | ||
else \ | ||
{ \ | ||
puts ("FAIL: " #TYPE " " #A " != " #B); \ | ||
result = 1; \ | ||
} \ | ||
} \ | ||
while (0) | ||
|
||
/* Cannot test payloads by memcmp for formats where NaNs have padding | ||
bits. */ | ||
#define CAN_TEST_EQ(MANT_DIG) ((MANT_DIG) != 64 && (MANT_DIG) != 106) | ||
|
||
#define RUN_TESTS(TYPE, SFUNC, FUNC, MANT_DIG) \ | ||
do \ | ||
{ \ | ||
TYPE n123 = WRAP_NAN (FUNC, "123"); \ | ||
CHECK_IS_NAN (TYPE, n123); \ | ||
TYPE s123 = WRAP_STRTO (SFUNC, "NAN(123)"); \ | ||
CHECK_IS_NAN (TYPE, s123); \ | ||
TYPE n456 = WRAP_NAN (FUNC, "456"); \ | ||
CHECK_IS_NAN (TYPE, n456); \ | ||
TYPE s456 = WRAP_STRTO (SFUNC, "NAN(456)"); \ | ||
CHECK_IS_NAN (TYPE, s456); \ | ||
TYPE n123x = WRAP_NAN (FUNC, "123)"); \ | ||
CHECK_IS_NAN (TYPE, n123x); \ | ||
TYPE nemp = WRAP_NAN (FUNC, ""); \ | ||
CHECK_IS_NAN (TYPE, nemp); \ | ||
TYPE semp = WRAP_STRTO (SFUNC, "NAN()"); \ | ||
CHECK_IS_NAN (TYPE, semp); \ | ||
TYPE sx = WRAP_STRTO (SFUNC, "NAN"); \ | ||
CHECK_IS_NAN (TYPE, sx); \ | ||
if (CAN_TEST_EQ (MANT_DIG)) \ | ||
CHECK_SAME_NAN (TYPE, n123, s123); \ | ||
if (CAN_TEST_EQ (MANT_DIG)) \ | ||
CHECK_SAME_NAN (TYPE, n456, s456); \ | ||
if (CAN_TEST_EQ (MANT_DIG)) \ | ||
CHECK_SAME_NAN (TYPE, nemp, semp); \ | ||
if (CAN_TEST_EQ (MANT_DIG)) \ | ||
CHECK_SAME_NAN (TYPE, n123x, sx); \ | ||
CHECK_DIFF_NAN (TYPE, n123, n456); \ | ||
CHECK_DIFF_NAN (TYPE, n123, nemp); \ | ||
CHECK_DIFF_NAN (TYPE, n123, n123x); \ | ||
CHECK_DIFF_NAN (TYPE, n456, nemp); \ | ||
CHECK_DIFF_NAN (TYPE, n456, n123x); \ | ||
} \ | ||
while (0) | ||
|
||
static int | ||
do_test (void) | ||
{ | ||
int result = 0; | ||
RUN_TESTS (float, strtof, nanf, FLT_MANT_DIG); | ||
RUN_TESTS (double, strtod, nan, DBL_MANT_DIG); | ||
#ifndef NO_LONG_DOUBLE | ||
RUN_TESTS (long double, strtold, nanl, LDBL_MANT_DIG); | ||
#endif | ||
return result; | ||
} | ||
|
||
#define TEST_FUNCTION do_test () | ||
#include "../test-skeleton.c" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters