forked from rpms/glibc
strtod: Fix subnormal rounding & errno; add new tests (RHEL-46739)
Resolves: RHEL-46739
This commit is contained in:
parent
52c06307bd
commit
66024333e7
49
glibc-RHEL-46739-1.patch
Normal file
49
glibc-RHEL-46739-1.patch
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
commit 207d64feb26279e152c50744e3c37e68491aca99
|
||||||
|
Author: Joseph Myers <josmyers@redhat.com>
|
||||||
|
Date: Wed Aug 14 17:15:46 2024 +0000
|
||||||
|
|
||||||
|
Test errno setting on strtod overflow in tst-strtod-round
|
||||||
|
|
||||||
|
We have no tests that errno is set to ERANGE on overflow of
|
||||||
|
strtod-family functions (we do have some tests for underflow, in
|
||||||
|
tst-strtod-underflow). Add such tests to tst-strtod-round.
|
||||||
|
|
||||||
|
Tested for x86_64.
|
||||||
|
|
||||||
|
diff --git a/stdlib/tst-strtod-round-skeleton.c b/stdlib/tst-strtod-round-skeleton.c
|
||||||
|
index f60b9a00e9e8d262..1ff1977112bda7a8 100644
|
||||||
|
--- a/stdlib/tst-strtod-round-skeleton.c
|
||||||
|
+++ b/stdlib/tst-strtod-round-skeleton.c
|
||||||
|
@@ -21,6 +21,7 @@
|
||||||
|
declared in the headers. */
|
||||||
|
#define _LIBC_TEST 1
|
||||||
|
#define __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||||
|
+#include <errno.h>
|
||||||
|
#include <fenv.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <math.h>
|
||||||
|
@@ -205,7 +206,9 @@ struct test {
|
||||||
|
#define GEN_ONE_TEST(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
|
||||||
|
{ \
|
||||||
|
feclearexcept (FE_ALL_EXCEPT); \
|
||||||
|
+ errno = 0; \
|
||||||
|
FTYPE f = STRTO (FSUF) (s, NULL); \
|
||||||
|
+ int new_errno = errno; \
|
||||||
|
if (f != expected->FSUF \
|
||||||
|
|| (copysign ## CSUF) (1.0 ## LSUF, f) \
|
||||||
|
!= (copysign ## CSUF) (1.0 ## LSUF, expected->FSUF)) \
|
||||||
|
@@ -254,6 +257,14 @@ struct test {
|
||||||
|
printf ("ignoring this exception error\n"); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
+ if (overflow->FSUF && new_errno != ERANGE) \
|
||||||
|
+ { \
|
||||||
|
+ printf (FNPFXS "to" #FSUF \
|
||||||
|
+ " (" STRM ") left errno == %d," \
|
||||||
|
+ " not %d (ERANGE)\n", \
|
||||||
|
+ s, new_errno, ERANGE); \
|
||||||
|
+ result = 1; \
|
||||||
|
+ } \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
38
glibc-RHEL-46739-10.patch
Normal file
38
glibc-RHEL-46739-10.patch
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
commit 378039ca578c2ea93095a1e710d96f58c68a3997
|
||||||
|
Author: Joseph Myers <josmyers@redhat.com>
|
||||||
|
Date: Fri Sep 20 23:24:45 2024 +0000
|
||||||
|
|
||||||
|
Add tests of more strtod special cases
|
||||||
|
|
||||||
|
There is very little test coverage of inputs to strtod-family
|
||||||
|
functions that don't contain anything that can be parsed as a number
|
||||||
|
(one test of ".y" in tst-strtod2), and none that I can see of skipping
|
||||||
|
initial whitespace. Add some tests of these things to tst-strtod2.
|
||||||
|
|
||||||
|
Tested for x86_64.
|
||||||
|
|
||||||
|
diff --git a/stdlib/tst-strtod2.c b/stdlib/tst-strtod2.c
|
||||||
|
index c84bd792c1a3f511..d00bc13323c50622 100644
|
||||||
|
--- a/stdlib/tst-strtod2.c
|
||||||
|
+++ b/stdlib/tst-strtod2.c
|
||||||
|
@@ -31,6 +31,20 @@ struct test_strto ## FSUF \
|
||||||
|
{ "0x1px", 1.0 ## LSUF, 3 }, \
|
||||||
|
{ "0x1p+x", 1.0 ## LSUF, 3 }, \
|
||||||
|
{ "0x1p-x", 1.0 ## LSUF, 3 }, \
|
||||||
|
+ { "", 0.0 ## LSUF, 0 }, \
|
||||||
|
+ { ".", 0.0 ## LSUF, 0 }, \
|
||||||
|
+ { "-", 0.0 ## LSUF, 0 }, \
|
||||||
|
+ { "-.", 0.0 ## LSUF, 0 }, \
|
||||||
|
+ { ".e", 0.0 ## LSUF, 0 }, \
|
||||||
|
+ { "-.e", 0.0 ## LSUF, 0 }, \
|
||||||
|
+ { " \t", 0.0 ## LSUF, 0 }, \
|
||||||
|
+ { " \t.", 0.0 ## LSUF, 0 }, \
|
||||||
|
+ { " \t-", 0.0 ## LSUF, 0 }, \
|
||||||
|
+ { " \t-.", 0.0 ## LSUF, 0 }, \
|
||||||
|
+ { " \t.e", 0.0 ## LSUF, 0 }, \
|
||||||
|
+ { " \t-.e", 0.0 ## LSUF, 0 }, \
|
||||||
|
+ { " \t\f\r\n\v1", 1.0 ## LSUF, 7 }, \
|
||||||
|
+ { " \t\f\r\n\v-1.5e2", -150.0 ## LSUF, 12 }, \
|
||||||
|
{ "INFx", INFINITY, 3 }, \
|
||||||
|
{ "infx", INFINITY, 3 }, \
|
||||||
|
{ "INFINITx", INFINITY, 3 }, \
|
439
glibc-RHEL-46739-11.patch
Normal file
439
glibc-RHEL-46739-11.patch
Normal file
@ -0,0 +1,439 @@
|
|||||||
|
commit 94ca2c0894f0e1b62625c369cc598a2b9236622c
|
||||||
|
Author: Joseph Myers <josmyers@redhat.com>
|
||||||
|
Date: Fri Sep 20 23:25:32 2024 +0000
|
||||||
|
|
||||||
|
Make tst-strtod-underflow type-generic
|
||||||
|
|
||||||
|
The test tst-strtod-underflow covers various edge cases close to the
|
||||||
|
underflow threshold for strtod (especially cases where underflow on
|
||||||
|
architectures with after-rounding tininess detection depends on the
|
||||||
|
rounding mode). Make it use the type-generic machinery, with
|
||||||
|
corresponding test inputs for each supported floating-point format, so
|
||||||
|
that other functions in the strtod family are tested for underflow
|
||||||
|
edge cases as well.
|
||||||
|
|
||||||
|
Tested for x86_64.
|
||||||
|
|
||||||
|
diff --git a/stdlib/tst-strtod-underflow.c b/stdlib/tst-strtod-underflow.c
|
||||||
|
index 294f88de439fb3e7..094a70bbbe53e70b 100644
|
||||||
|
--- a/stdlib/tst-strtod-underflow.c
|
||||||
|
+++ b/stdlib/tst-strtod-underflow.c
|
||||||
|
@@ -17,6 +17,10 @@
|
||||||
|
License along with the GNU C Library; if not, see
|
||||||
|
<https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
+/* Defining _LIBC_TEST ensures long double math functions are
|
||||||
|
+ declared in the headers. */
|
||||||
|
+#define _LIBC_TEST 1
|
||||||
|
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fenv.h>
|
||||||
|
#include <float.h>
|
||||||
|
@@ -25,6 +29,60 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <tininess.h>
|
||||||
|
|
||||||
|
+#include "tst-strtod.h"
|
||||||
|
+
|
||||||
|
+/* Logic for selecting between tests for different formats is as in
|
||||||
|
+ tst-strtod-skeleton.c, but here it is selecting string inputs with
|
||||||
|
+ different underflow properties, rather than generated test
|
||||||
|
+ data. */
|
||||||
|
+
|
||||||
|
+#define _CONCAT(a, b) a ## b
|
||||||
|
+#define CONCAT(a, b) _CONCAT (a, b)
|
||||||
|
+
|
||||||
|
+#define MEMBER(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
|
||||||
|
+ const char *s_ ## FSUF;
|
||||||
|
+
|
||||||
|
+#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
|
||||||
|
+# define CHOOSE_ld(f,d,...) d
|
||||||
|
+#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && LDBL_MIN_EXP == -16381
|
||||||
|
+# define CHOOSE_ld(f,d,ld64i,...) ld64i
|
||||||
|
+#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && LDBL_MIN_EXP == -16382
|
||||||
|
+# define CHOOSE_ld(f,d,ld64i,ld64m,...) ld64m
|
||||||
|
+#elif LDBL_MANT_DIG == 106 && LDBL_MAX_EXP == 1024
|
||||||
|
+# define CHOOSE_ld(f,d,ld64i,ld64m,ld106,...) ld106
|
||||||
|
+#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384
|
||||||
|
+# define CHOOSE_ld(f,d,ld64i,ld64m,ld106,ld113,...) ld113
|
||||||
|
+#else
|
||||||
|
+# error "unknown long double format"
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#define CHOOSE_f(f,...) f
|
||||||
|
+#define CHOOSE_f32(f,...) f
|
||||||
|
+#define CHOOSE_d(f,d,...) d
|
||||||
|
+#define CHOOSE_f64(f,d,...) d
|
||||||
|
+#define CHOOSE_f32x(f,d,...) d
|
||||||
|
+#define CHOOSE_f128(f,d,ld64i,ld64m,ld106,ld113,...) ld113
|
||||||
|
+
|
||||||
|
+#if __HAVE_FLOAT64X
|
||||||
|
+# if FLT64X_MANT_DIG == 113 && FLT64X_MAX_EXP == 16384
|
||||||
|
+# define CHOOSE_f64x(f,d,ld64i,ld64m,ld106,ld113,...) ld113
|
||||||
|
+# elif (FLT64X_MANT_DIG == 64 \
|
||||||
|
+ && FLT64X_MAX_EXP == 16384 \
|
||||||
|
+ && FLT64X_MIN_EXP == -16381)
|
||||||
|
+# define CHOOSE_f64x(f,d,ld64i,...) ld64i
|
||||||
|
+# else
|
||||||
|
+# error "unknown _Float64x format"
|
||||||
|
+# endif
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#define _XNTRY(FSUF, FTYPE, FTOSTR, LSUF, CSUF, ...) \
|
||||||
|
+ CHOOSE_ ## FSUF (__VA_ARGS__),
|
||||||
|
+#define XNTRY(...) \
|
||||||
|
+ GEN_TEST_STRTOD_FOREACH (_XNTRY, __VA_ARGS__)
|
||||||
|
+
|
||||||
|
+#define TEST(f, d, ld64i, ld64m, ld106, ld113, u) \
|
||||||
|
+ { XNTRY(f, d, ld64i, ld64m, ld106, ld113) u }
|
||||||
|
+
|
||||||
|
enum underflow_case
|
||||||
|
{
|
||||||
|
/* Result is exact or outside the subnormal range. */
|
||||||
|
@@ -55,38 +113,194 @@ enum underflow_case
|
||||||
|
|
||||||
|
struct test
|
||||||
|
{
|
||||||
|
- const char *s;
|
||||||
|
+ GEN_TEST_STRTOD_FOREACH (MEMBER)
|
||||||
|
enum underflow_case c;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct test tests[] =
|
||||||
|
{
|
||||||
|
- { "0x1p-1022", UNDERFLOW_NONE },
|
||||||
|
- { "-0x1p-1022", UNDERFLOW_NONE },
|
||||||
|
- { "0x0p-10000000000000000000000000", UNDERFLOW_NONE },
|
||||||
|
- { "-0x0p-10000000000000000000000000", UNDERFLOW_NONE },
|
||||||
|
- { "0x1p-10000000000000000000000000", UNDERFLOW_ALWAYS },
|
||||||
|
- { "-0x1p-10000000000000000000000000", UNDERFLOW_ALWAYS },
|
||||||
|
- { "0x1.000000000000000000001p-1022", UNDERFLOW_NONE },
|
||||||
|
- { "-0x1.000000000000000000001p-1022", UNDERFLOW_NONE },
|
||||||
|
- { "0x1p-1075", UNDERFLOW_ALWAYS },
|
||||||
|
- { "-0x1p-1075", UNDERFLOW_ALWAYS },
|
||||||
|
- { "0x1p-1023", UNDERFLOW_NONE },
|
||||||
|
- { "-0x1p-1023", UNDERFLOW_NONE },
|
||||||
|
- { "0x1p-1074", UNDERFLOW_NONE },
|
||||||
|
- { "-0x1p-1074", UNDERFLOW_NONE },
|
||||||
|
- { "0x1.ffffffffffffep-1023", UNDERFLOW_NONE },
|
||||||
|
- { "-0x1.ffffffffffffep-1023", UNDERFLOW_NONE },
|
||||||
|
- { "0x1.fffffffffffffp-1023", UNDERFLOW_ALWAYS },
|
||||||
|
- { "-0x1.fffffffffffffp-1023", UNDERFLOW_ALWAYS },
|
||||||
|
- { "0x1.fffffffffffff0001p-1023", UNDERFLOW_EXCEPT_UPWARD },
|
||||||
|
- { "-0x1.fffffffffffff0001p-1023", UNDERFLOW_EXCEPT_DOWNWARD },
|
||||||
|
- { "0x1.fffffffffffff7fffp-1023", UNDERFLOW_EXCEPT_UPWARD },
|
||||||
|
- { "-0x1.fffffffffffff7fffp-1023", UNDERFLOW_EXCEPT_DOWNWARD },
|
||||||
|
- { "0x1.fffffffffffff8p-1023", UNDERFLOW_ONLY_DOWNWARD_ZERO },
|
||||||
|
- { "-0x1.fffffffffffff8p-1023", UNDERFLOW_ONLY_UPWARD_ZERO },
|
||||||
|
- { "0x1.fffffffffffffffffp-1023", UNDERFLOW_ONLY_DOWNWARD_ZERO },
|
||||||
|
- { "-0x1.fffffffffffffffffp-1023", UNDERFLOW_ONLY_UPWARD_ZERO },
|
||||||
|
+ TEST ("0x1p-126",
|
||||||
|
+ "0x1p-1022",
|
||||||
|
+ "0x1p-16382",
|
||||||
|
+ "0x1p-16383",
|
||||||
|
+ "0x1p-969",
|
||||||
|
+ "0x1p-16382",
|
||||||
|
+ UNDERFLOW_NONE),
|
||||||
|
+ TEST ("-0x1p-126",
|
||||||
|
+ "-0x1p-1022",
|
||||||
|
+ "-0x1p-16382",
|
||||||
|
+ "-0x1p-16383",
|
||||||
|
+ "-0x1p-969",
|
||||||
|
+ "-0x1p-16382",
|
||||||
|
+ UNDERFLOW_NONE),
|
||||||
|
+ TEST ("0x0p-10000000000000000000000000",
|
||||||
|
+ "0x0p-10000000000000000000000000",
|
||||||
|
+ "0x0p-10000000000000000000000000",
|
||||||
|
+ "0x0p-10000000000000000000000000",
|
||||||
|
+ "0x0p-10000000000000000000000000",
|
||||||
|
+ "0x0p-10000000000000000000000000",
|
||||||
|
+ UNDERFLOW_NONE),
|
||||||
|
+ TEST ("-0x0p-10000000000000000000000000",
|
||||||
|
+ "-0x0p-10000000000000000000000000",
|
||||||
|
+ "-0x0p-10000000000000000000000000",
|
||||||
|
+ "-0x0p-10000000000000000000000000",
|
||||||
|
+ "-0x0p-10000000000000000000000000",
|
||||||
|
+ "-0x0p-10000000000000000000000000",
|
||||||
|
+ UNDERFLOW_NONE),
|
||||||
|
+ TEST ("0x1p-10000000000000000000000000",
|
||||||
|
+ "0x1p-10000000000000000000000000",
|
||||||
|
+ "0x1p-10000000000000000000000000",
|
||||||
|
+ "0x1p-10000000000000000000000000",
|
||||||
|
+ "0x1p-10000000000000000000000000",
|
||||||
|
+ "0x1p-10000000000000000000000000",
|
||||||
|
+ UNDERFLOW_ALWAYS),
|
||||||
|
+ TEST ("-0x1p-10000000000000000000000000",
|
||||||
|
+ "-0x1p-10000000000000000000000000",
|
||||||
|
+ "-0x1p-10000000000000000000000000",
|
||||||
|
+ "-0x1p-10000000000000000000000000",
|
||||||
|
+ "-0x1p-10000000000000000000000000",
|
||||||
|
+ "-0x1p-10000000000000000000000000",
|
||||||
|
+ UNDERFLOW_ALWAYS),
|
||||||
|
+ TEST ("0x1.000000000000000000001p-126",
|
||||||
|
+ "0x1.000000000000000000001p-1022",
|
||||||
|
+ "0x1.000000000000000000001p-16382",
|
||||||
|
+ "0x1.000000000000000000001p-16383",
|
||||||
|
+ "0x1.000000000000000000001p-969",
|
||||||
|
+ "0x1.00000000000000000000000000000000000000001p-16382",
|
||||||
|
+ UNDERFLOW_NONE),
|
||||||
|
+ TEST ("-0x1.000000000000000000001p-126",
|
||||||
|
+ "-0x1.000000000000000000001p-1022",
|
||||||
|
+ "-0x1.000000000000000000001p-16382",
|
||||||
|
+ "-0x1.000000000000000000001p-16383",
|
||||||
|
+ "-0x1.000000000000000000001p-969",
|
||||||
|
+ "-0x1.00000000000000000000000000000000000000001p-16382",
|
||||||
|
+ UNDERFLOW_NONE),
|
||||||
|
+ TEST ("0x1p-150",
|
||||||
|
+ "0x1p-1075",
|
||||||
|
+ "0x1p-16446",
|
||||||
|
+ "0x1p-16447",
|
||||||
|
+ "0x1p-1075",
|
||||||
|
+ "0x1p-16495",
|
||||||
|
+ UNDERFLOW_ALWAYS),
|
||||||
|
+ TEST ("-0x1p-150",
|
||||||
|
+ "-0x1p-1075",
|
||||||
|
+ "-0x1p-16446",
|
||||||
|
+ "-0x1p-16447",
|
||||||
|
+ "-0x1p-1075",
|
||||||
|
+ "-0x1p-16495",
|
||||||
|
+ UNDERFLOW_ALWAYS),
|
||||||
|
+ TEST ("0x1p-127",
|
||||||
|
+ "0x1p-1023",
|
||||||
|
+ "0x1p-16383",
|
||||||
|
+ "0x1p-16384",
|
||||||
|
+ "0x1p-970",
|
||||||
|
+ "0x1p-16383",
|
||||||
|
+ UNDERFLOW_NONE),
|
||||||
|
+ TEST ("-0x1p-127",
|
||||||
|
+ "-0x1p-1023",
|
||||||
|
+ "-0x1p-16383",
|
||||||
|
+ "-0x1p-16384",
|
||||||
|
+ "-0x1p-970",
|
||||||
|
+ "-0x1p-16383",
|
||||||
|
+ UNDERFLOW_NONE),
|
||||||
|
+ TEST ("0x1p-149",
|
||||||
|
+ "0x1p-1074",
|
||||||
|
+ "0x1p-16445",
|
||||||
|
+ "0x1p-16446",
|
||||||
|
+ "0x1p-1074",
|
||||||
|
+ "0x1p-16494",
|
||||||
|
+ UNDERFLOW_NONE),
|
||||||
|
+ TEST ("-0x1p-149",
|
||||||
|
+ "-0x1p-1074",
|
||||||
|
+ "-0x1p-16445",
|
||||||
|
+ "-0x1p-16446",
|
||||||
|
+ "-0x1p-1074",
|
||||||
|
+ "-0x1p-16494",
|
||||||
|
+ UNDERFLOW_NONE),
|
||||||
|
+ TEST ("0x1.fffffcp-127",
|
||||||
|
+ "0x1.ffffffffffffep-1023",
|
||||||
|
+ "0x1.fffffffffffffffcp-16383",
|
||||||
|
+ "0x1.fffffffffffffffcp-16384",
|
||||||
|
+ "0x1.ffffffffffffffffffffffffffp-970",
|
||||||
|
+ "0x1.fffffffffffffffffffffffffffep-16383",
|
||||||
|
+ UNDERFLOW_NONE),
|
||||||
|
+ TEST ("-0x1.fffffcp-127",
|
||||||
|
+ "-0x1.ffffffffffffep-1023",
|
||||||
|
+ "-0x1.fffffffffffffffcp-16383",
|
||||||
|
+ "-0x1.fffffffffffffffcp-16384",
|
||||||
|
+ "-0x1.ffffffffffffffffffffffffffp-970",
|
||||||
|
+ "-0x1.fffffffffffffffffffffffffffep-16383",
|
||||||
|
+ UNDERFLOW_NONE),
|
||||||
|
+ TEST ("0x1.fffffep-127",
|
||||||
|
+ "0x1.fffffffffffffp-1023",
|
||||||
|
+ "0x1.fffffffffffffffep-16383",
|
||||||
|
+ "0x1.fffffffffffffffep-16384",
|
||||||
|
+ "0x1.ffffffffffffffffffffffffff8p-970",
|
||||||
|
+ "0x1.ffffffffffffffffffffffffffffp-16383",
|
||||||
|
+ UNDERFLOW_ALWAYS),
|
||||||
|
+ TEST ("-0x1.fffffep-127",
|
||||||
|
+ "-0x1.fffffffffffffp-1023",
|
||||||
|
+ "-0x1.fffffffffffffffep-16383",
|
||||||
|
+ "-0x1.fffffffffffffffep-16384",
|
||||||
|
+ "-0x1.ffffffffffffffffffffffffff8p-970",
|
||||||
|
+ "-0x1.ffffffffffffffffffffffffffffp-16383",
|
||||||
|
+ UNDERFLOW_ALWAYS),
|
||||||
|
+ TEST ("0x1.fffffe0001p-127",
|
||||||
|
+ "0x1.fffffffffffff0001p-1023",
|
||||||
|
+ "0x1.fffffffffffffffe0001p-16383",
|
||||||
|
+ "0x1.fffffffffffffffe0001p-16384",
|
||||||
|
+ "0x1.ffffffffffffffffffffffffff80001p-970",
|
||||||
|
+ "0x1.ffffffffffffffffffffffffffff0001p-16383",
|
||||||
|
+ UNDERFLOW_EXCEPT_UPWARD),
|
||||||
|
+ TEST ("-0x1.fffffe0001p-127",
|
||||||
|
+ "-0x1.fffffffffffff0001p-1023",
|
||||||
|
+ "-0x1.fffffffffffffffe0001p-16383",
|
||||||
|
+ "-0x1.fffffffffffffffe0001p-16384",
|
||||||
|
+ "-0x1.ffffffffffffffffffffffffff80001p-970",
|
||||||
|
+ "-0x1.ffffffffffffffffffffffffffff0001p-16383",
|
||||||
|
+ UNDERFLOW_EXCEPT_DOWNWARD),
|
||||||
|
+ TEST ("0x1.fffffeffffp-127",
|
||||||
|
+ "0x1.fffffffffffff7fffp-1023",
|
||||||
|
+ "0x1.fffffffffffffffeffffp-16383",
|
||||||
|
+ "0x1.fffffffffffffffeffffp-16384",
|
||||||
|
+ "0x1.ffffffffffffffffffffffffffbffffp-970",
|
||||||
|
+ "0x1.ffffffffffffffffffffffffffff7fffp-16383",
|
||||||
|
+ UNDERFLOW_EXCEPT_UPWARD),
|
||||||
|
+ TEST ("-0x1.fffffeffffp-127",
|
||||||
|
+ "-0x1.fffffffffffff7fffp-1023",
|
||||||
|
+ "-0x1.fffffffffffffffeffffp-16383",
|
||||||
|
+ "-0x1.fffffffffffffffeffffp-16384",
|
||||||
|
+ "-0x1.ffffffffffffffffffffffffffbffffp-970",
|
||||||
|
+ "-0x1.ffffffffffffffffffffffffffff7fffp-16383",
|
||||||
|
+ UNDERFLOW_EXCEPT_DOWNWARD),
|
||||||
|
+ TEST ("0x1.ffffffp-127",
|
||||||
|
+ "0x1.fffffffffffff8p-1023",
|
||||||
|
+ "0x1.ffffffffffffffffp-16383",
|
||||||
|
+ "0x1.ffffffffffffffffp-16384",
|
||||||
|
+ "0x1.ffffffffffffffffffffffffffcp-970",
|
||||||
|
+ "0x1.ffffffffffffffffffffffffffff8p-16383",
|
||||||
|
+ UNDERFLOW_ONLY_DOWNWARD_ZERO),
|
||||||
|
+ TEST ("-0x1.ffffffp-127",
|
||||||
|
+ "-0x1.fffffffffffff8p-1023",
|
||||||
|
+ "-0x1.ffffffffffffffffp-16383",
|
||||||
|
+ "-0x1.ffffffffffffffffp-16384",
|
||||||
|
+ "-0x1.ffffffffffffffffffffffffffcp-970",
|
||||||
|
+ "-0x1.ffffffffffffffffffffffffffff8p-16383",
|
||||||
|
+ UNDERFLOW_ONLY_UPWARD_ZERO),
|
||||||
|
+ TEST ("0x1.ffffffffffp-127",
|
||||||
|
+ "0x1.fffffffffffffffffp-1023",
|
||||||
|
+ "0x1.ffffffffffffffffffffp-16383",
|
||||||
|
+ "0x1.ffffffffffffffffffffp-16384",
|
||||||
|
+ "0x1.ffffffffffffffffffffffffffffffp-970",
|
||||||
|
+ "0x1.ffffffffffffffffffffffffffffffffp-16383",
|
||||||
|
+ UNDERFLOW_ONLY_DOWNWARD_ZERO),
|
||||||
|
+ TEST ("-0x1.ffffffffffp-127",
|
||||||
|
+ "-0x1.fffffffffffffffffp-1023",
|
||||||
|
+ "-0x1.ffffffffffffffffffffp-16383",
|
||||||
|
+ "-0x1.ffffffffffffffffffffp-16384",
|
||||||
|
+ "-0x1.ffffffffffffffffffffffffffffffp-970",
|
||||||
|
+ "-0x1.ffffffffffffffffffffffffffffffffp-16383",
|
||||||
|
+ UNDERFLOW_ONLY_UPWARD_ZERO),
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Return whether to expect underflow from a particular testcase, in a
|
||||||
|
@@ -133,39 +347,62 @@ static bool support_underflow_exception = false;
|
||||||
|
volatile double d = DBL_MIN;
|
||||||
|
volatile double dd;
|
||||||
|
|
||||||
|
-static int
|
||||||
|
-test_in_one_mode (const char *s, enum underflow_case c, int rm,
|
||||||
|
- const char *mode_name)
|
||||||
|
+static bool
|
||||||
|
+test_got_fe_underflow (void)
|
||||||
|
{
|
||||||
|
- int result = 0;
|
||||||
|
- feclearexcept (FE_ALL_EXCEPT);
|
||||||
|
- errno = 0;
|
||||||
|
- double d = strtod (s, NULL);
|
||||||
|
- int got_errno = errno;
|
||||||
|
#ifdef FE_UNDERFLOW
|
||||||
|
- bool got_fe_underflow = fetestexcept (FE_UNDERFLOW) != 0;
|
||||||
|
+ return fetestexcept (FE_UNDERFLOW) != 0;
|
||||||
|
#else
|
||||||
|
- bool got_fe_underflow = false;
|
||||||
|
+ return false;
|
||||||
|
#endif
|
||||||
|
- printf ("strtod (%s) (%s) returned %a, errno = %d, %sunderflow exception\n",
|
||||||
|
- s, mode_name, d, got_errno, got_fe_underflow ? "" : "no ");
|
||||||
|
- bool this_expect_underflow = expect_underflow (c, rm);
|
||||||
|
- if (got_errno != 0 && got_errno != ERANGE)
|
||||||
|
- {
|
||||||
|
- puts ("FAIL: errno neither 0 nor ERANGE");
|
||||||
|
- result = 1;
|
||||||
|
- }
|
||||||
|
- else if (this_expect_underflow != (errno == ERANGE))
|
||||||
|
- {
|
||||||
|
- puts ("FAIL: underflow from errno differs from expectations");
|
||||||
|
- result = 1;
|
||||||
|
- }
|
||||||
|
- if (support_underflow_exception && got_fe_underflow != this_expect_underflow)
|
||||||
|
- {
|
||||||
|
- puts ("FAIL: underflow from exceptions differs from expectations");
|
||||||
|
- result = 1;
|
||||||
|
- }
|
||||||
|
- return result;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
|
||||||
|
+static int \
|
||||||
|
+test_strto ## FSUF (int i, int rm, const char *mode_name) \
|
||||||
|
+{ \
|
||||||
|
+ const char *s = tests[i].s_ ## FSUF; \
|
||||||
|
+ enum underflow_case c = tests[i].c; \
|
||||||
|
+ int result = 0; \
|
||||||
|
+ feclearexcept (FE_ALL_EXCEPT); \
|
||||||
|
+ errno = 0; \
|
||||||
|
+ FTYPE d = strto ## FSUF (s, NULL); \
|
||||||
|
+ int got_errno = errno; \
|
||||||
|
+ bool got_fe_underflow = test_got_fe_underflow (); \
|
||||||
|
+ char buf[FSTRLENMAX]; \
|
||||||
|
+ FTOSTR (buf, sizeof (buf), "%a", d); \
|
||||||
|
+ printf ("strto" #FSUF \
|
||||||
|
+ " (%s) (%s) returned %s, errno = %d, " \
|
||||||
|
+ "%sunderflow exception\n", \
|
||||||
|
+ s, mode_name, buf, got_errno, \
|
||||||
|
+ got_fe_underflow ? "" : "no "); \
|
||||||
|
+ bool this_expect_underflow = expect_underflow (c, rm); \
|
||||||
|
+ if (got_errno != 0 && got_errno != ERANGE) \
|
||||||
|
+ { \
|
||||||
|
+ puts ("FAIL: errno neither 0 nor ERANGE"); \
|
||||||
|
+ result = 1; \
|
||||||
|
+ } \
|
||||||
|
+ else if (this_expect_underflow != (errno == ERANGE)) \
|
||||||
|
+ { \
|
||||||
|
+ puts ("FAIL: underflow from errno differs from expectations"); \
|
||||||
|
+ result = 1; \
|
||||||
|
+ } \
|
||||||
|
+ if (support_underflow_exception \
|
||||||
|
+ && got_fe_underflow != this_expect_underflow) \
|
||||||
|
+ { \
|
||||||
|
+ puts ("FAIL: underflow from exceptions " \
|
||||||
|
+ "differs from expectations"); \
|
||||||
|
+ result = 1; \
|
||||||
|
+ } \
|
||||||
|
+ return result; \
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+GEN_TEST_STRTOD_FOREACH (TEST_STRTOD)
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+test_in_one_mode (size_t i, int rm, const char *mode_name)
|
||||||
|
+{
|
||||||
|
+ return STRTOD_TEST_FOREACH (test_strto, i, rm, mode_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
@@ -191,12 +428,12 @@ do_test (void)
|
||||||
|
#endif
|
||||||
|
for (size_t i = 0; i < sizeof (tests) / sizeof (tests[0]); i++)
|
||||||
|
{
|
||||||
|
- result |= test_in_one_mode (tests[i].s, tests[i].c, fe_tonearest,
|
||||||
|
+ result |= test_in_one_mode (i, fe_tonearest,
|
||||||
|
"default rounding mode");
|
||||||
|
#ifdef FE_DOWNWARD
|
||||||
|
if (!fesetround (FE_DOWNWARD))
|
||||||
|
{
|
||||||
|
- result |= test_in_one_mode (tests[i].s, tests[i].c, FE_DOWNWARD,
|
||||||
|
+ result |= test_in_one_mode (i, FE_DOWNWARD,
|
||||||
|
"FE_DOWNWARD");
|
||||||
|
fesetround (save_round_mode);
|
||||||
|
}
|
||||||
|
@@ -204,7 +441,7 @@ do_test (void)
|
||||||
|
#ifdef FE_TOWARDZERO
|
||||||
|
if (!fesetround (FE_TOWARDZERO))
|
||||||
|
{
|
||||||
|
- result |= test_in_one_mode (tests[i].s, tests[i].c, FE_TOWARDZERO,
|
||||||
|
+ result |= test_in_one_mode (i, FE_TOWARDZERO,
|
||||||
|
"FE_TOWARDZERO");
|
||||||
|
fesetround (save_round_mode);
|
||||||
|
}
|
||||||
|
@@ -212,7 +449,7 @@ do_test (void)
|
||||||
|
#ifdef FE_UPWARD
|
||||||
|
if (!fesetround (FE_UPWARD))
|
||||||
|
{
|
||||||
|
- result |= test_in_one_mode (tests[i].s, tests[i].c, FE_UPWARD,
|
||||||
|
+ result |= test_in_one_mode (i, FE_UPWARD,
|
||||||
|
"FE_UPWARD");
|
||||||
|
fesetround (save_round_mode);
|
||||||
|
}
|
16723
glibc-RHEL-46739-2.patch
Normal file
16723
glibc-RHEL-46739-2.patch
Normal file
File diff suppressed because it is too large
Load Diff
445
glibc-RHEL-46739-3.patch
Normal file
445
glibc-RHEL-46739-3.patch
Normal file
@ -0,0 +1,445 @@
|
|||||||
|
commit 457622c2fa8f9f7435822d5287a437bc8be8090d
|
||||||
|
Author: Joseph Myers <josmyers@redhat.com>
|
||||||
|
Date: Tue Aug 27 12:41:02 2024 +0000
|
||||||
|
|
||||||
|
Fix strtod subnormal rounding (bug 30220)
|
||||||
|
|
||||||
|
As reported in bug 30220, the implementation of strtod-family
|
||||||
|
functions has a bug in the following case: the input string would,
|
||||||
|
with infinite exponent range, take one more bit to represent than is
|
||||||
|
available in the normal precision of the return type; the value
|
||||||
|
represented is in the subnormal range; and there are no nonzero bits
|
||||||
|
in the value, below those that can be represented in subnormal
|
||||||
|
precision, other than the least significant bit and possibly the
|
||||||
|
0.5ulp bit. In this case, round_and_return ends up discarding the
|
||||||
|
least significant bit.
|
||||||
|
|
||||||
|
Fix by saving that bit to merge into more_bits (it can't be merged in
|
||||||
|
at the time it's computed, because more_bits mustn't include this bit
|
||||||
|
in the case of after-rounding tininess detection checking if the
|
||||||
|
result is still subnormal when rounded to normal precision, so merging
|
||||||
|
this bit into more_bits needs to take place after that check).
|
||||||
|
|
||||||
|
Tested for x86_64.
|
||||||
|
|
||||||
|
diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c
|
||||||
|
index 5a54d99ae8663641..49b88e9a86be8441 100644
|
||||||
|
--- a/stdlib/strtod_l.c
|
||||||
|
+++ b/stdlib/strtod_l.c
|
||||||
|
@@ -223,6 +223,7 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
|
||||||
|
|
||||||
|
mp_size_t shift = MIN_EXP - 1 - exponent;
|
||||||
|
bool is_tiny = true;
|
||||||
|
+ bool old_half_bit = (round_limb & (((mp_limb_t) 1) << round_bit)) != 0;
|
||||||
|
|
||||||
|
more_bits |= (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0;
|
||||||
|
if (shift == MANT_DIG)
|
||||||
|
@@ -293,6 +294,7 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
|
||||||
|
round_bit = shift - 1;
|
||||||
|
(void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, shift);
|
||||||
|
}
|
||||||
|
+ more_bits |= old_half_bit;
|
||||||
|
/* This is a hook for the m68k long double format, where the
|
||||||
|
exponent bias is the same for normalized and denormalized
|
||||||
|
numbers. */
|
||||||
|
diff --git a/stdlib/tst-strtod-round-data b/stdlib/tst-strtod-round-data
|
||||||
|
index 84ab705709b24b6c..9489fbcc9ce7eee2 100644
|
||||||
|
--- a/stdlib/tst-strtod-round-data
|
||||||
|
+++ b/stdlib/tst-strtod-round-data
|
||||||
|
@@ -265,3 +265,15 @@
|
||||||
|
1.000000000000000000000000000000000385185988877447170611195588516985463707620329643077639047987759113311767578125
|
||||||
|
1.0000000000000000000000000000000001925929944387235853055977942584927318538101648215388195239938795566558837890625
|
||||||
|
1.00000000000000000000000000000000009629649721936179265279889712924636592690508241076940976199693977832794189453125
|
||||||
|
+0x30000002222225p-1077
|
||||||
|
+0x0.7fffffffffffeap-1022
|
||||||
|
+0x0.7fffffffffffe9p-1022
|
||||||
|
+0x0.7ffffd4p-126
|
||||||
|
+0x0.7ffffffffffffffd4p-16382
|
||||||
|
+0x0.7ffffffffffffffd4p-16383
|
||||||
|
+0x0.7ffffffffffffffffffffffffffeap-16382
|
||||||
|
+0x0.7000004p-126
|
||||||
|
+0x0.70000000000002p-1022
|
||||||
|
+0x0.70000000000000004p-16382
|
||||||
|
+0x0.70000000000000004p-16383
|
||||||
|
+0x0.70000000000000000000000000002p-16382
|
||||||
|
diff --git a/stdlib/tst-strtod-round-data.h b/stdlib/tst-strtod-round-data.h
|
||||||
|
index 13e62dd2b0588a16..ed50eb2537bc175c 100644
|
||||||
|
--- a/stdlib/tst-strtod-round-data.h
|
||||||
|
+++ b/stdlib/tst-strtod-round-data.h
|
||||||
|
@@ -15437,4 +15437,376 @@ static const struct test tests[] = {
|
||||||
|
0x1p+0, false, false,
|
||||||
|
0x1p+0, false, false,
|
||||||
|
0x1.0000000000000000000000000001p+0, false, false),
|
||||||
|
+ TEST ("0x30000002222225p-1077",
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x8p-152, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.800000111111p-1024, false, true,
|
||||||
|
+ 0x1.8000001111114p-1024, false, true,
|
||||||
|
+ 0x1.800000111111p-1024, false, true,
|
||||||
|
+ 0x1.8000001111114p-1024, false, true,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.80000011111128p-1024, false, false,
|
||||||
|
+ 0x1.80000011111128p-1024, false, false,
|
||||||
|
+ 0x1.80000011111128p-1024, false, false,
|
||||||
|
+ 0x1.80000011111128p-1024, false, false,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.80000011111128p-1024, false, false,
|
||||||
|
+ 0x1.80000011111128p-1024, false, false,
|
||||||
|
+ 0x1.80000011111128p-1024, false, false,
|
||||||
|
+ 0x1.80000011111128p-1024, false, false,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.800000111111p-1024, false, true,
|
||||||
|
+ 0x1.8000001111114p-1024, false, true,
|
||||||
|
+ 0x1.800000111111p-1024, false, true,
|
||||||
|
+ 0x1.8000001111114p-1024, false, true,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.80000011111128p-1024, false, false,
|
||||||
|
+ 0x1.80000011111128p-1024, false, false,
|
||||||
|
+ 0x1.80000011111128p-1024, false, false,
|
||||||
|
+ 0x1.80000011111128p-1024, false, false),
|
||||||
|
+ TEST ("0x0.7fffffffffffeap-1022",
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x8p-152, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.ffffffffffff8p-1024, false, true,
|
||||||
|
+ 0x1.ffffffffffffcp-1024, false, true,
|
||||||
|
+ 0x1.ffffffffffff8p-1024, false, true,
|
||||||
|
+ 0x1.ffffffffffffcp-1024, false, true,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.ffffffffffffa8p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa8p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa8p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa8p-1024, false, false,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.ffffffffffffa8p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa8p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa8p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa8p-1024, false, false,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.ffffffffffff8p-1024, false, true,
|
||||||
|
+ 0x1.ffffffffffffcp-1024, false, true,
|
||||||
|
+ 0x1.ffffffffffff8p-1024, false, true,
|
||||||
|
+ 0x1.ffffffffffffcp-1024, false, true,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.ffffffffffffa8p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa8p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa8p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa8p-1024, false, false),
|
||||||
|
+ TEST ("0x0.7fffffffffffe9p-1022",
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x8p-152, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.ffffffffffff8p-1024, false, true,
|
||||||
|
+ 0x1.ffffffffffffcp-1024, false, true,
|
||||||
|
+ 0x1.ffffffffffff8p-1024, false, true,
|
||||||
|
+ 0x1.ffffffffffffcp-1024, false, true,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.ffffffffffffa4p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa4p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa4p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa4p-1024, false, false,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.ffffffffffffa4p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa4p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa4p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa4p-1024, false, false,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.ffffffffffff8p-1024, false, true,
|
||||||
|
+ 0x1.ffffffffffffcp-1024, false, true,
|
||||||
|
+ 0x1.ffffffffffff8p-1024, false, true,
|
||||||
|
+ 0x1.ffffffffffffcp-1024, false, true,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.ffffffffffffa4p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa4p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa4p-1024, false, false,
|
||||||
|
+ 0x1.ffffffffffffa4p-1024, false, false),
|
||||||
|
+ TEST ("0x0.7ffffd4p-126",
|
||||||
|
+ false,
|
||||||
|
+ 0x1.fffffp-128, false, true,
|
||||||
|
+ 0x1.fffff8p-128, false, true,
|
||||||
|
+ 0x1.fffffp-128, false, true,
|
||||||
|
+ 0x1.fffff8p-128, false, true,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ 0x1.fffff5p-128, false, false,
|
||||||
|
+ 0x1.fffff5p-128, false, false),
|
||||||
|
+ TEST ("0x0.7ffffffffffffffd4p-16382",
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x8p-152, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x4p-1076, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.fffffffffffffffp-16384, false, true,
|
||||||
|
+ 0x1.fffffffffffffff8p-16384, false, true,
|
||||||
|
+ 0x1.fffffffffffffffp-16384, false, true,
|
||||||
|
+ 0x1.fffffffffffffff8p-16384, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.fffffffffffffff4p-16384, false, true,
|
||||||
|
+ 0x1.fffffffffffffff4p-16384, false, true,
|
||||||
|
+ 0x1.fffffffffffffff4p-16384, false, true,
|
||||||
|
+ 0x1.fffffffffffffff8p-16384, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x4p-1076, false, true,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.fffffffffffffff5p-16384, false, false,
|
||||||
|
+ 0x1.fffffffffffffff5p-16384, false, false,
|
||||||
|
+ 0x1.fffffffffffffff5p-16384, false, false,
|
||||||
|
+ 0x1.fffffffffffffff5p-16384, false, false),
|
||||||
|
+ TEST ("0x0.7ffffffffffffffd4p-16383",
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x8p-152, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x4p-1076, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0xf.ffffffffffffff8p-16388, false, true,
|
||||||
|
+ 0xf.ffffffffffffff8p-16388, false, true,
|
||||||
|
+ 0xf.ffffffffffffff8p-16388, false, true,
|
||||||
|
+ 0x1p-16384, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0xf.ffffffffffffff8p-16388, false, true,
|
||||||
|
+ 0xf.ffffffffffffffcp-16388, false, true,
|
||||||
|
+ 0xf.ffffffffffffff8p-16388, false, true,
|
||||||
|
+ 0xf.ffffffffffffffcp-16388, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x4p-1076, false, true,
|
||||||
|
+ true,
|
||||||
|
+ 0xf.ffffffffffffffa8p-16388, false, false,
|
||||||
|
+ 0xf.ffffffffffffffa8p-16388, false, false,
|
||||||
|
+ 0xf.ffffffffffffffa8p-16388, false, false,
|
||||||
|
+ 0xf.ffffffffffffffa8p-16388, false, false),
|
||||||
|
+ TEST ("0x0.7ffffffffffffffffffffffffffeap-16382",
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x8p-152, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x4p-1076, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.fffffffffffffff8p-16384, false, true,
|
||||||
|
+ 0x2p-16384, false, true,
|
||||||
|
+ 0x1.fffffffffffffff8p-16384, false, true,
|
||||||
|
+ 0x2p-16384, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.fffffffffffffffcp-16384, false, true,
|
||||||
|
+ 0x2p-16384, false, true,
|
||||||
|
+ 0x1.fffffffffffffffcp-16384, false, true,
|
||||||
|
+ 0x2p-16384, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x4p-1076, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.fffffffffffffffffffffffffff8p-16384, false, true,
|
||||||
|
+ 0x1.fffffffffffffffffffffffffffcp-16384, false, true,
|
||||||
|
+ 0x1.fffffffffffffffffffffffffff8p-16384, false, true,
|
||||||
|
+ 0x1.fffffffffffffffffffffffffffcp-16384, false, true),
|
||||||
|
+ TEST ("0x0.7000004p-126",
|
||||||
|
+ false,
|
||||||
|
+ 0x1.cp-128, false, true,
|
||||||
|
+ 0x1.cp-128, false, true,
|
||||||
|
+ 0x1.cp-128, false, true,
|
||||||
|
+ 0x1.c00008p-128, false, true,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ 0x1.c00001p-128, false, false,
|
||||||
|
+ 0x1.c00001p-128, false, false),
|
||||||
|
+ TEST ("0x0.70000000000002p-1022",
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x8p-152, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.cp-1024, false, true,
|
||||||
|
+ 0x1.cp-1024, false, true,
|
||||||
|
+ 0x1.cp-1024, false, true,
|
||||||
|
+ 0x1.c000000000004p-1024, false, true,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.c0000000000008p-1024, false, false,
|
||||||
|
+ 0x1.c0000000000008p-1024, false, false,
|
||||||
|
+ 0x1.c0000000000008p-1024, false, false,
|
||||||
|
+ 0x1.c0000000000008p-1024, false, false,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.c0000000000008p-1024, false, false,
|
||||||
|
+ 0x1.c0000000000008p-1024, false, false,
|
||||||
|
+ 0x1.c0000000000008p-1024, false, false,
|
||||||
|
+ 0x1.c0000000000008p-1024, false, false,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.cp-1024, false, true,
|
||||||
|
+ 0x1.cp-1024, false, true,
|
||||||
|
+ 0x1.cp-1024, false, true,
|
||||||
|
+ 0x1.c000000000004p-1024, false, true,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.c0000000000008p-1024, false, false,
|
||||||
|
+ 0x1.c0000000000008p-1024, false, false,
|
||||||
|
+ 0x1.c0000000000008p-1024, false, false,
|
||||||
|
+ 0x1.c0000000000008p-1024, false, false),
|
||||||
|
+ TEST ("0x0.70000000000000004p-16382",
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x8p-152, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x4p-1076, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.cp-16384, false, true,
|
||||||
|
+ 0x1.cp-16384, false, true,
|
||||||
|
+ 0x1.cp-16384, false, true,
|
||||||
|
+ 0x1.c000000000000008p-16384, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.cp-16384, false, true,
|
||||||
|
+ 0x1.cp-16384, false, true,
|
||||||
|
+ 0x1.cp-16384, false, true,
|
||||||
|
+ 0x1.c000000000000004p-16384, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x4p-1076, false, true,
|
||||||
|
+ true,
|
||||||
|
+ 0x1.c000000000000001p-16384, false, false,
|
||||||
|
+ 0x1.c000000000000001p-16384, false, false,
|
||||||
|
+ 0x1.c000000000000001p-16384, false, false,
|
||||||
|
+ 0x1.c000000000000001p-16384, false, false),
|
||||||
|
+ TEST ("0x0.70000000000000004p-16383",
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x8p-152, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x4p-1076, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0xep-16388, false, true,
|
||||||
|
+ 0xep-16388, false, true,
|
||||||
|
+ 0xep-16388, false, true,
|
||||||
|
+ 0xe.000000000000008p-16388, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0xep-16388, false, true,
|
||||||
|
+ 0xep-16388, false, true,
|
||||||
|
+ 0xep-16388, false, true,
|
||||||
|
+ 0xe.000000000000004p-16388, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x4p-1076, false, true,
|
||||||
|
+ true,
|
||||||
|
+ 0xe.0000000000000008p-16388, false, false,
|
||||||
|
+ 0xe.0000000000000008p-16388, false, false,
|
||||||
|
+ 0xe.0000000000000008p-16388, false, false,
|
||||||
|
+ 0xe.0000000000000008p-16388, false, false),
|
||||||
|
+ TEST ("0x0.70000000000000000000000000002p-16382",
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x8p-152, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x4p-1076, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.cp-16384, false, true,
|
||||||
|
+ 0x1.cp-16384, false, true,
|
||||||
|
+ 0x1.cp-16384, false, true,
|
||||||
|
+ 0x1.c000000000000008p-16384, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.cp-16384, false, true,
|
||||||
|
+ 0x1.cp-16384, false, true,
|
||||||
|
+ 0x1.cp-16384, false, true,
|
||||||
|
+ 0x1.c000000000000004p-16384, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x0p+0, false, true,
|
||||||
|
+ 0x4p-1076, false, true,
|
||||||
|
+ false,
|
||||||
|
+ 0x1.cp-16384, false, true,
|
||||||
|
+ 0x1.cp-16384, false, true,
|
||||||
|
+ 0x1.cp-16384, false, true,
|
||||||
|
+ 0x1.c000000000000000000000000004p-16384, false, true),
|
||||||
|
};
|
598
glibc-RHEL-46739-4.patch
Normal file
598
glibc-RHEL-46739-4.patch
Normal file
@ -0,0 +1,598 @@
|
|||||||
|
commit 3fc063dee01da4f80920a14b7db637c8501d6fd4
|
||||||
|
Author: Joseph Myers <josmyers@redhat.com>
|
||||||
|
Date: Tue Aug 27 20:41:54 2024 +0000
|
||||||
|
|
||||||
|
Make __strtod_internal tests type-generic
|
||||||
|
|
||||||
|
Some of the strtod tests use type-generic machinery in tst-strtod.h to
|
||||||
|
test the strto* functions for all floating types, while others only
|
||||||
|
test double even when the tests are in fact meaningful for all
|
||||||
|
floating types.
|
||||||
|
|
||||||
|
Convert the tests of the internal __strtod_internal interface to cover
|
||||||
|
all floating types. I haven't tried to convert them to use newer test
|
||||||
|
interfaces in other ways, just made the changes necessary to use the
|
||||||
|
type-generic machinery. As an internal interface, there are no
|
||||||
|
aliases for different types with the same ABI (however,
|
||||||
|
__strtold_internal is defined even if long double has the same ABI as
|
||||||
|
double), so macros used by the type-generic testing code are redefined
|
||||||
|
as needed to avoid expecting such aliases to be present.
|
||||||
|
|
||||||
|
Tested for x86_64.
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
stdlib/tst-strtod4.c
|
||||||
|
(69239bd7a216007692470aa9d5f3658024638742 missing downstream)
|
||||||
|
|
||||||
|
diff --git a/stdlib/tst-strtod1i.c b/stdlib/tst-strtod1i.c
|
||||||
|
index 98fc5d527fe1edd9..32fc8b9e1f08ace9 100644
|
||||||
|
--- a/stdlib/tst-strtod1i.c
|
||||||
|
+++ b/stdlib/tst-strtod1i.c
|
||||||
|
@@ -25,60 +25,91 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
-/* Perform a few tests in a locale with thousands separators. */
|
||||||
|
-static int
|
||||||
|
-do_test (void)
|
||||||
|
-{
|
||||||
|
- static const struct
|
||||||
|
- {
|
||||||
|
- const char *loc;
|
||||||
|
- const char *str;
|
||||||
|
- double exp;
|
||||||
|
- ptrdiff_t nread;
|
||||||
|
- } tests[] =
|
||||||
|
- {
|
||||||
|
- { "de_DE.UTF-8", "1,5", 1.5, 3 },
|
||||||
|
- { "de_DE.UTF-8", "1.5", 1.0, 1 },
|
||||||
|
- { "de_DE.UTF-8", "1.500", 1500.0, 5 },
|
||||||
|
- { "de_DE.UTF-8", "36.893.488.147.419.103.232", 0x1.0p65, 26 }
|
||||||
|
- };
|
||||||
|
-#define ntests (sizeof (tests) / sizeof (tests[0]))
|
||||||
|
- size_t n;
|
||||||
|
- int result = 0;
|
||||||
|
-
|
||||||
|
- puts ("\nLocale tests");
|
||||||
|
+#include "tst-strtod.h"
|
||||||
|
|
||||||
|
- for (n = 0; n < ntests; ++n)
|
||||||
|
- {
|
||||||
|
- double d;
|
||||||
|
- char *endp;
|
||||||
|
+/* This tests internal interfaces, which are only defined for types
|
||||||
|
+ with distinct ABIs, so disable testing for types without distinct
|
||||||
|
+ ABIs. */
|
||||||
|
+#undef IF_FLOAT32
|
||||||
|
+#define IF_FLOAT32(x)
|
||||||
|
+#undef IF_FLOAT64
|
||||||
|
+#define IF_FLOAT64(x)
|
||||||
|
+#undef IF_FLOAT32X
|
||||||
|
+#define IF_FLOAT32X(x)
|
||||||
|
+#undef IF_FLOAT64X
|
||||||
|
+#define IF_FLOAT64X(x)
|
||||||
|
+#if !__HAVE_DISTINCT_FLOAT128
|
||||||
|
+# undef IF_FLOAT128
|
||||||
|
+# define IF_FLOAT128(x)
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
- if (setlocale (LC_ALL, tests[n].loc) == NULL)
|
||||||
|
- {
|
||||||
|
- printf ("cannot set locale %s\n", tests[n].loc);
|
||||||
|
- result = 1;
|
||||||
|
- continue;
|
||||||
|
- }
|
||||||
|
+#define ntests (sizeof (tests) / sizeof (tests[0]))
|
||||||
|
|
||||||
|
- d = __strtod_internal (tests[n].str, &endp, 1);
|
||||||
|
- if (d != tests[n].exp)
|
||||||
|
- {
|
||||||
|
- printf ("strtod(\"%s\") returns %g and not %g\n",
|
||||||
|
- tests[n].str, d, tests[n].exp);
|
||||||
|
- result = 1;
|
||||||
|
- }
|
||||||
|
- else if (endp - tests[n].str != tests[n].nread)
|
||||||
|
- {
|
||||||
|
- printf ("strtod(\"%s\") read %td bytes and not %td\n",
|
||||||
|
- tests[n].str, endp - tests[n].str, tests[n].nread);
|
||||||
|
- result = 1;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+/* Perform a few tests in a locale with thousands separators. */
|
||||||
|
+#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
|
||||||
|
+static int \
|
||||||
|
+test_strto ## FSUF (void) \
|
||||||
|
+{ \
|
||||||
|
+ static const struct \
|
||||||
|
+ { \
|
||||||
|
+ const char *loc; \
|
||||||
|
+ const char *str; \
|
||||||
|
+ FTYPE exp; \
|
||||||
|
+ ptrdiff_t nread; \
|
||||||
|
+ } tests[] = \
|
||||||
|
+ { \
|
||||||
|
+ { "de_DE.UTF-8", "1,5", 1.5 ## LSUF, 3 }, \
|
||||||
|
+ { "de_DE.UTF-8", "1.5", 1.0 ## LSUF, 1 }, \
|
||||||
|
+ { "de_DE.UTF-8", "1.500", 1500.0 ## LSUF, 5 }, \
|
||||||
|
+ { "de_DE.UTF-8", "36.893.488.147.419.103.232", 0x1.0p65 ## LSUF, 26 } \
|
||||||
|
+ }; \
|
||||||
|
+ size_t n; \
|
||||||
|
+ int result = 0; \
|
||||||
|
+ \
|
||||||
|
+ puts ("\nLocale tests"); \
|
||||||
|
+ \
|
||||||
|
+ for (n = 0; n < ntests; ++n) \
|
||||||
|
+ { \
|
||||||
|
+ FTYPE d; \
|
||||||
|
+ char *endp; \
|
||||||
|
+ \
|
||||||
|
+ if (setlocale (LC_ALL, tests[n].loc) == NULL) \
|
||||||
|
+ { \
|
||||||
|
+ printf ("cannot set locale %s\n", tests[n].loc); \
|
||||||
|
+ result = 1; \
|
||||||
|
+ continue; \
|
||||||
|
+ } \
|
||||||
|
+ \
|
||||||
|
+ d = __strto ## FSUF ## _internal (tests[n].str, &endp, 1); \
|
||||||
|
+ if (d != tests[n].exp) \
|
||||||
|
+ { \
|
||||||
|
+ char buf1[FSTRLENMAX], buf2[FSTRLENMAX]; \
|
||||||
|
+ FTOSTR (buf1, sizeof (buf1), "%g", d); \
|
||||||
|
+ FTOSTR (buf2, sizeof (buf2), "%g", tests[n].exp); \
|
||||||
|
+ printf ("strto" # FSUF "(\"%s\") returns %s and not %s\n", \
|
||||||
|
+ tests[n].str, buf1, buf2); \
|
||||||
|
+ result = 1; \
|
||||||
|
+ } \
|
||||||
|
+ else if (endp - tests[n].str != tests[n].nread) \
|
||||||
|
+ { \
|
||||||
|
+ printf ("strto" # FSUF "(\"%s\") read %td bytes and not %td\n", \
|
||||||
|
+ tests[n].str, endp - tests[n].str, tests[n].nread); \
|
||||||
|
+ result = 1; \
|
||||||
|
+ } \
|
||||||
|
+ } \
|
||||||
|
+ \
|
||||||
|
+ if (result == 0) \
|
||||||
|
+ puts ("all OK"); \
|
||||||
|
+ \
|
||||||
|
+ return result ? EXIT_FAILURE : EXIT_SUCCESS; \
|
||||||
|
+}
|
||||||
|
|
||||||
|
- if (result == 0)
|
||||||
|
- puts ("all OK");
|
||||||
|
+GEN_TEST_STRTOD_FOREACH (TEST_STRTOD)
|
||||||
|
|
||||||
|
- return result ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ return STRTOD_TEST_FOREACH (test_strto);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <support/test-driver.c>
|
||||||
|
diff --git a/stdlib/tst-strtod3.c b/stdlib/tst-strtod3.c
|
||||||
|
index 23abec1896896276..0d662d8be83a7525 100644
|
||||||
|
--- a/stdlib/tst-strtod3.c
|
||||||
|
+++ b/stdlib/tst-strtod3.c
|
||||||
|
@@ -3,19 +3,73 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
-static const struct
|
||||||
|
-{
|
||||||
|
- const char *in;
|
||||||
|
- const char *out;
|
||||||
|
- double expected;
|
||||||
|
-} tests[] =
|
||||||
|
- {
|
||||||
|
- { "000,,,e1", ",,,e1", 0.0 },
|
||||||
|
- { "000e1", "", 0.0 },
|
||||||
|
- { "000,1e1", ",1e1", 0.0 }
|
||||||
|
- };
|
||||||
|
-#define NTESTS (sizeof (tests) / sizeof (tests[0]))
|
||||||
|
+#include "tst-strtod.h"
|
||||||
|
+
|
||||||
|
+/* This tests internal interfaces, which are only defined for types
|
||||||
|
+ with distinct ABIs, so disable testing for types without distinct
|
||||||
|
+ ABIs. */
|
||||||
|
+#undef IF_FLOAT32
|
||||||
|
+#define IF_FLOAT32(x)
|
||||||
|
+#undef IF_FLOAT64
|
||||||
|
+#define IF_FLOAT64(x)
|
||||||
|
+#undef IF_FLOAT32X
|
||||||
|
+#define IF_FLOAT32X(x)
|
||||||
|
+#undef IF_FLOAT64X
|
||||||
|
+#define IF_FLOAT64X(x)
|
||||||
|
+#if !__HAVE_DISTINCT_FLOAT128
|
||||||
|
+# undef IF_FLOAT128
|
||||||
|
+# define IF_FLOAT128(x)
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
+#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
|
||||||
|
+static const struct \
|
||||||
|
+{ \
|
||||||
|
+ const char *in; \
|
||||||
|
+ const char *out; \
|
||||||
|
+ FTYPE expected; \
|
||||||
|
+} tests_strto ## FSUF[] = \
|
||||||
|
+ { \
|
||||||
|
+ { "000,,,e1", ",,,e1", 0.0 ## LSUF }, \
|
||||||
|
+ { "000e1", "", 0.0 ## LSUF }, \
|
||||||
|
+ { "000,1e1", ",1e1", 0.0 ## LSUF } \
|
||||||
|
+ }; \
|
||||||
|
+ \
|
||||||
|
+static int \
|
||||||
|
+test_strto ## FSUF (void) \
|
||||||
|
+{ \
|
||||||
|
+ int status = 0; \
|
||||||
|
+ \
|
||||||
|
+ for (int i = 0; \
|
||||||
|
+ i < sizeof (tests_strto ## FSUF) / sizeof (tests_strto ## FSUF[0]); \
|
||||||
|
+ ++i) \
|
||||||
|
+ { \
|
||||||
|
+ char *ep; \
|
||||||
|
+ FTYPE r = __strto ## FSUF ## _internal (tests_strto ## FSUF[i].in, \
|
||||||
|
+ &ep, 1); \
|
||||||
|
+ \
|
||||||
|
+ if (strcmp (ep, tests_strto ## FSUF[i].out) != 0) \
|
||||||
|
+ { \
|
||||||
|
+ printf ("%d: got rest string \"%s\", expected \"%s\"\n", \
|
||||||
|
+ i, ep, tests_strto ## FSUF[i].out); \
|
||||||
|
+ status = 1; \
|
||||||
|
+ } \
|
||||||
|
+ \
|
||||||
|
+ if (r != tests_strto ## FSUF[i].expected) \
|
||||||
|
+ { \
|
||||||
|
+ char buf1[FSTRLENMAX], buf2[FSTRLENMAX]; \
|
||||||
|
+ FTOSTR (buf1, sizeof (buf1), "%g", r); \
|
||||||
|
+ FTOSTR (buf2, sizeof (buf2), "%g", \
|
||||||
|
+ tests_strto ## FSUF[i].expected); \
|
||||||
|
+ printf ("%d: got wrong results %s, expected %s\n", \
|
||||||
|
+ i, buf1, buf2); \
|
||||||
|
+ status = 1; \
|
||||||
|
+ } \
|
||||||
|
+ } \
|
||||||
|
+ \
|
||||||
|
+ return status; \
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+GEN_TEST_STRTOD_FOREACH (TEST_STRTOD)
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
@@ -26,29 +80,7 @@ do_test (void)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- int status = 0;
|
||||||
|
-
|
||||||
|
- for (int i = 0; i < NTESTS; ++i)
|
||||||
|
- {
|
||||||
|
- char *ep;
|
||||||
|
- double r = __strtod_internal (tests[i].in, &ep, 1);
|
||||||
|
-
|
||||||
|
- if (strcmp (ep, tests[i].out) != 0)
|
||||||
|
- {
|
||||||
|
- printf ("%d: got rest string \"%s\", expected \"%s\"\n",
|
||||||
|
- i, ep, tests[i].out);
|
||||||
|
- status = 1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (r != tests[i].expected)
|
||||||
|
- {
|
||||||
|
- printf ("%d: got wrong results %g, expected %g\n",
|
||||||
|
- i, r, tests[i].expected);
|
||||||
|
- status = 1;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return status;
|
||||||
|
+ return STRTOD_TEST_FOREACH (test_strto);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_FUNCTION do_test ()
|
||||||
|
diff --git a/stdlib/tst-strtod4.c b/stdlib/tst-strtod4.c
|
||||||
|
index aae9835d82d38b4e..cd86f8c1f13a39e4 100644
|
||||||
|
--- a/stdlib/tst-strtod4.c
|
||||||
|
+++ b/stdlib/tst-strtod4.c
|
||||||
|
@@ -3,20 +3,74 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
+#include "tst-strtod.h"
|
||||||
|
+
|
||||||
|
+/* This tests internal interfaces, which are only defined for types
|
||||||
|
+ with distinct ABIs, so disable testing for types without distinct
|
||||||
|
+ ABIs. */
|
||||||
|
+#undef IF_FLOAT32
|
||||||
|
+#define IF_FLOAT32(x)
|
||||||
|
+#undef IF_FLOAT64
|
||||||
|
+#define IF_FLOAT64(x)
|
||||||
|
+#undef IF_FLOAT32X
|
||||||
|
+#define IF_FLOAT32X(x)
|
||||||
|
+#undef IF_FLOAT64X
|
||||||
|
+#define IF_FLOAT64X(x)
|
||||||
|
+#if !__HAVE_DISTINCT_FLOAT128
|
||||||
|
+# undef IF_FLOAT128
|
||||||
|
+# define IF_FLOAT128(x)
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
#define NNBSP "\xe2\x80\xaf"
|
||||||
|
|
||||||
|
-static const struct
|
||||||
|
-{
|
||||||
|
- const char *in;
|
||||||
|
- const char *out;
|
||||||
|
- double expected;
|
||||||
|
-} tests[] =
|
||||||
|
- {
|
||||||
|
- { "000"NNBSP"000"NNBSP"000", "", 0.0 },
|
||||||
|
- { "1"NNBSP"000"NNBSP"000,5x", "x", 1000000.5 }
|
||||||
|
- };
|
||||||
|
-#define NTESTS (sizeof (tests) / sizeof (tests[0]))
|
||||||
|
+#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
|
||||||
|
+static const struct \
|
||||||
|
+{ \
|
||||||
|
+ const char *in; \
|
||||||
|
+ const char *out; \
|
||||||
|
+ FTYPE expected; \
|
||||||
|
+} tests_strto ## FSUF[] = \
|
||||||
|
+ { \
|
||||||
|
+ { "000"NNBSP"000"NNBSP"000", "", 0.0 ## LSUF }, \
|
||||||
|
+ { "1"NNBSP"000"NNBSP"000,5x", "x", 1000000.5 ## LSUF } \
|
||||||
|
+ }; \
|
||||||
|
+ \
|
||||||
|
+static int \
|
||||||
|
+test_strto ## FSUF (void) \
|
||||||
|
+{ \
|
||||||
|
+ int status = 0; \
|
||||||
|
+ \
|
||||||
|
+ for (int i = 0; \
|
||||||
|
+ i < sizeof (tests_strto ## FSUF) / sizeof (tests_strto ## FSUF[0]); \
|
||||||
|
+ ++i) \
|
||||||
|
+ { \
|
||||||
|
+ char *ep; \
|
||||||
|
+ FTYPE r = __strto ## FSUF ## _internal (tests_strto ## FSUF[i].in, \
|
||||||
|
+ &ep, 1); \
|
||||||
|
+ \
|
||||||
|
+ if (strcmp (ep, tests_strto ## FSUF[i].out) != 0) \
|
||||||
|
+ { \
|
||||||
|
+ printf ("%d: got rest string \"%s\", expected \"%s\"\n", \
|
||||||
|
+ i, ep, tests_strto ## FSUF[i].out); \
|
||||||
|
+ status = 1; \
|
||||||
|
+ } \
|
||||||
|
+ \
|
||||||
|
+ if (r != tests_strto ## FSUF[i].expected) \
|
||||||
|
+ { \
|
||||||
|
+ char buf1[FSTRLENMAX], buf2[FSTRLENMAX]; \
|
||||||
|
+ FTOSTR (buf1, sizeof (buf1), "%g", r); \
|
||||||
|
+ FTOSTR (buf2, sizeof (buf2), "%g", \
|
||||||
|
+ tests_strto ## FSUF[i].expected); \
|
||||||
|
+ printf ("%d: got wrong results %s, expected %s\n", \
|
||||||
|
+ i, buf1, buf2); \
|
||||||
|
+ status = 1; \
|
||||||
|
+ } \
|
||||||
|
+ } \
|
||||||
|
+ \
|
||||||
|
+ return status; \
|
||||||
|
+}
|
||||||
|
|
||||||
|
+GEN_TEST_STRTOD_FOREACH (TEST_STRTOD)
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
@@ -27,29 +81,7 @@ do_test (void)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- int status = 0;
|
||||||
|
-
|
||||||
|
- for (int i = 0; i < NTESTS; ++i)
|
||||||
|
- {
|
||||||
|
- char *ep;
|
||||||
|
- double r = __strtod_internal (tests[i].in, &ep, 1);
|
||||||
|
-
|
||||||
|
- if (strcmp (ep, tests[i].out) != 0)
|
||||||
|
- {
|
||||||
|
- printf ("%d: got rest string \"%s\", expected \"%s\"\n",
|
||||||
|
- i, ep, tests[i].out);
|
||||||
|
- status = 1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (r != tests[i].expected)
|
||||||
|
- {
|
||||||
|
- printf ("%d: got wrong results %g, expected %g\n",
|
||||||
|
- i, r, tests[i].expected);
|
||||||
|
- status = 1;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return status;
|
||||||
|
+ return STRTOD_TEST_FOREACH (test_strto);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_FUNCTION do_test ()
|
||||||
|
diff --git a/stdlib/tst-strtod5i.c b/stdlib/tst-strtod5i.c
|
||||||
|
index ba3e78d5f2933586..0ddae2b94765de39 100644
|
||||||
|
--- a/stdlib/tst-strtod5i.c
|
||||||
|
+++ b/stdlib/tst-strtod5i.c
|
||||||
|
@@ -16,52 +16,112 @@
|
||||||
|
License along with the GNU C Library; if not, see
|
||||||
|
<https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
+/* Defining _LIBC_TEST ensures long double math functions are
|
||||||
|
+ declared in the headers. */
|
||||||
|
+#define _LIBC_TEST 1
|
||||||
|
#include <locale.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
+#include "tst-strtod.h"
|
||||||
|
+
|
||||||
|
+/* This tests internal interfaces, which are only defined for types
|
||||||
|
+ with distinct ABIs, so disable testing for types without distinct
|
||||||
|
+ ABIs. */
|
||||||
|
+#undef IF_FLOAT32
|
||||||
|
+#define IF_FLOAT32(x)
|
||||||
|
+#undef IF_FLOAT64
|
||||||
|
+#define IF_FLOAT64(x)
|
||||||
|
+#undef IF_FLOAT32X
|
||||||
|
+#define IF_FLOAT32X(x)
|
||||||
|
+#undef IF_FLOAT64X
|
||||||
|
+#define IF_FLOAT64X(x)
|
||||||
|
+#if !__HAVE_DISTINCT_FLOAT128
|
||||||
|
+# undef IF_FLOAT128
|
||||||
|
+# define IF_FLOAT128(x)
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
#define NNBSP "\xe2\x80\xaf"
|
||||||
|
|
||||||
|
-static const struct
|
||||||
|
-{
|
||||||
|
- const char *in;
|
||||||
|
- int group;
|
||||||
|
- double expected;
|
||||||
|
-} tests[] =
|
||||||
|
- {
|
||||||
|
- { "0", 0, 0.0 },
|
||||||
|
- { "000", 0, 0.0 },
|
||||||
|
- { "-0", 0, -0.0 },
|
||||||
|
- { "-000", 0, -0.0 },
|
||||||
|
- { "0,", 0, 0.0 },
|
||||||
|
- { "-0,", 0, -0.0 },
|
||||||
|
- { "0,0", 0, 0.0 },
|
||||||
|
- { "-0,0", 0, -0.0 },
|
||||||
|
- { "0e-10", 0, 0.0 },
|
||||||
|
- { "-0e-10", 0, -0.0 },
|
||||||
|
- { "0,e-10", 0, 0.0 },
|
||||||
|
- { "-0,e-10", 0, -0.0 },
|
||||||
|
- { "0,0e-10", 0, 0.0 },
|
||||||
|
- { "-0,0e-10", 0, -0.0 },
|
||||||
|
- { "0e-1000000", 0, 0.0 },
|
||||||
|
- { "-0e-1000000", 0, -0.0 },
|
||||||
|
- { "0,0e-1000000", 0, 0.0 },
|
||||||
|
- { "-0,0e-1000000", 0, -0.0 },
|
||||||
|
- { "0", 1, 0.0 },
|
||||||
|
- { "000", 1, 0.0 },
|
||||||
|
- { "-0", 1, -0.0 },
|
||||||
|
- { "-000", 1, -0.0 },
|
||||||
|
- { "0e-10", 1, 0.0 },
|
||||||
|
- { "-0e-10", 1, -0.0 },
|
||||||
|
- { "0e-1000000", 1, 0.0 },
|
||||||
|
- { "-0e-1000000", 1, -0.0 },
|
||||||
|
- { "000"NNBSP"000"NNBSP"000", 1, 0.0 },
|
||||||
|
- { "-000"NNBSP"000"NNBSP"000", 1, -0.0 }
|
||||||
|
- };
|
||||||
|
-#define NTESTS (sizeof (tests) / sizeof (tests[0]))
|
||||||
|
+#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
|
||||||
|
+static const struct \
|
||||||
|
+{ \
|
||||||
|
+ const char *in; \
|
||||||
|
+ int group; \
|
||||||
|
+ FTYPE expected; \
|
||||||
|
+} tests_strto ## FSUF[] = \
|
||||||
|
+ { \
|
||||||
|
+ { "0", 0, 0.0 ## LSUF }, \
|
||||||
|
+ { "000", 0, 0.0 ## LSUF }, \
|
||||||
|
+ { "-0", 0, -0.0 ## LSUF }, \
|
||||||
|
+ { "-000", 0, -0.0 ## LSUF }, \
|
||||||
|
+ { "0,", 0, 0.0 ## LSUF }, \
|
||||||
|
+ { "-0,", 0, -0.0 ## LSUF }, \
|
||||||
|
+ { "0,0", 0, 0.0 ## LSUF }, \
|
||||||
|
+ { "-0,0", 0, -0.0 ## LSUF }, \
|
||||||
|
+ { "0e-10", 0, 0.0 ## LSUF }, \
|
||||||
|
+ { "-0e-10", 0, -0.0 ## LSUF }, \
|
||||||
|
+ { "0,e-10", 0, 0.0 ## LSUF }, \
|
||||||
|
+ { "-0,e-10", 0, -0.0 ## LSUF }, \
|
||||||
|
+ { "0,0e-10", 0, 0.0 ## LSUF }, \
|
||||||
|
+ { "-0,0e-10", 0, -0.0 ## LSUF }, \
|
||||||
|
+ { "0e-1000000", 0, 0.0 ## LSUF }, \
|
||||||
|
+ { "-0e-1000000", 0, -0.0 ## LSUF }, \
|
||||||
|
+ { "0,0e-1000000", 0, 0.0 ## LSUF }, \
|
||||||
|
+ { "-0,0e-1000000", 0, -0.0 ## LSUF }, \
|
||||||
|
+ { "0", 1, 0.0 ## LSUF }, \
|
||||||
|
+ { "000", 1, 0.0 ## LSUF }, \
|
||||||
|
+ { "-0", 1, -0.0 ## LSUF }, \
|
||||||
|
+ { "-000", 1, -0.0 ## LSUF }, \
|
||||||
|
+ { "0e-10", 1, 0.0 ## LSUF }, \
|
||||||
|
+ { "-0e-10", 1, -0.0 ## LSUF }, \
|
||||||
|
+ { "0e-1000000", 1, 0.0 ## LSUF }, \
|
||||||
|
+ { "-0e-1000000", 1, -0.0 ## LSUF }, \
|
||||||
|
+ { "000"NNBSP"000"NNBSP"000", 1, 0.0 ## LSUF }, \
|
||||||
|
+ { "-000"NNBSP"000"NNBSP"000", 1, -0.0 ## LSUF } \
|
||||||
|
+ }; \
|
||||||
|
+ \
|
||||||
|
+static int \
|
||||||
|
+test_strto ## FSUF (void) \
|
||||||
|
+{ \
|
||||||
|
+ int status = 0; \
|
||||||
|
+ \
|
||||||
|
+ for (int i = 0; \
|
||||||
|
+ i < sizeof (tests_strto ## FSUF) / sizeof (tests_strto ## FSUF[0]); \
|
||||||
|
+ ++i) \
|
||||||
|
+ { \
|
||||||
|
+ char *ep; \
|
||||||
|
+ FTYPE r = __strto ## FSUF ## _internal (tests_strto ## FSUF[i].in, \
|
||||||
|
+ &ep, \
|
||||||
|
+ tests_strto ## FSUF[i].group); \
|
||||||
|
+ \
|
||||||
|
+ if (*ep != '\0') \
|
||||||
|
+ { \
|
||||||
|
+ printf ("%d: got rest string \"%s\", expected \"\"\n", i, ep); \
|
||||||
|
+ status = 1; \
|
||||||
|
+ } \
|
||||||
|
+ \
|
||||||
|
+ if (r != tests_strto ## FSUF[i].expected \
|
||||||
|
+ || (copysign ## CSUF (10.0 ## LSUF, r) \
|
||||||
|
+ != copysign ## CSUF (10.0 ## LSUF, \
|
||||||
|
+ tests_strto ## FSUF[i].expected))) \
|
||||||
|
+ { \
|
||||||
|
+ char buf1[FSTRLENMAX], buf2[FSTRLENMAX]; \
|
||||||
|
+ FTOSTR (buf1, sizeof (buf1), "%g", r); \
|
||||||
|
+ FTOSTR (buf2, sizeof (buf2), "%g", \
|
||||||
|
+ tests_strto ## FSUF[i].expected); \
|
||||||
|
+ printf ("%d: got wrong results %s, expected %s\n", \
|
||||||
|
+ i, buf1, buf2); \
|
||||||
|
+ status = 1; \
|
||||||
|
+ } \
|
||||||
|
+ } \
|
||||||
|
+ \
|
||||||
|
+ return status; \
|
||||||
|
+}
|
||||||
|
|
||||||
|
+GEN_TEST_STRTOD_FOREACH (TEST_STRTOD)
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
@@ -72,29 +132,7 @@ do_test (void)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- int status = 0;
|
||||||
|
-
|
||||||
|
- for (int i = 0; i < NTESTS; ++i)
|
||||||
|
- {
|
||||||
|
- char *ep;
|
||||||
|
- double r = __strtod_internal (tests[i].in, &ep, tests[i].group);
|
||||||
|
-
|
||||||
|
- if (*ep != '\0')
|
||||||
|
- {
|
||||||
|
- printf ("%d: got rest string \"%s\", expected \"\"\n", i, ep);
|
||||||
|
- status = 1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (r != tests[i].expected
|
||||||
|
- || copysign (10.0, r) != copysign (10.0, tests[i].expected))
|
||||||
|
- {
|
||||||
|
- printf ("%d: got wrong results %g, expected %g\n",
|
||||||
|
- i, r, tests[i].expected);
|
||||||
|
- status = 1;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return status;
|
||||||
|
+ return STRTOD_TEST_FOREACH (test_strto);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <support/test-driver.c>
|
140
glibc-RHEL-46739-5.patch
Normal file
140
glibc-RHEL-46739-5.patch
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
commit be77d5ae417236883c02d3d67c0716e3f669fa41
|
||||||
|
Author: Joseph Myers <josmyers@redhat.com>
|
||||||
|
Date: Wed Sep 4 13:20:18 2024 +0000
|
||||||
|
|
||||||
|
Improve NaN payload testing
|
||||||
|
|
||||||
|
There are two separate sets of tests of NaN payloads in glibc:
|
||||||
|
|
||||||
|
* libm-test-{get,set}payload* verify that getpayload, setpayload,
|
||||||
|
setpayloadsig and __builtin_nan functions are consistent in their
|
||||||
|
payload handling.
|
||||||
|
|
||||||
|
* test-nan-payload verifies that strtod-family functions and the
|
||||||
|
not-built-in nan functions are consistent in their payload handling.
|
||||||
|
|
||||||
|
Nothing, however, connects the two sets of functions (i.e., verifies
|
||||||
|
that strtod / nan are consistent with getpayload / setpayload /
|
||||||
|
__builtin_nan).
|
||||||
|
|
||||||
|
Improve test-nan-payload to check actual payload value with getpayload
|
||||||
|
rather than just verifying that the strtod and nan functions produce
|
||||||
|
the same NaN. Also check that the NaNs produced aren't signaling and
|
||||||
|
extend the tests to cover _FloatN / _FloatNx.
|
||||||
|
|
||||||
|
Tested for x86_64.
|
||||||
|
|
||||||
|
diff --git a/math/test-nan-payload.c b/math/test-nan-payload.c
|
||||||
|
index 88fd727e63b2fda2..0ee5432d40a3f997 100644
|
||||||
|
--- a/math/test-nan-payload.c
|
||||||
|
+++ b/math/test-nan-payload.c
|
||||||
|
@@ -16,6 +16,8 @@
|
||||||
|
License along with the GNU C Library; if not, see
|
||||||
|
<https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
+#define _LIBC_TEST 1
|
||||||
|
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||||
|
#include <float.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
@@ -31,7 +33,7 @@
|
||||||
|
#define CHECK_IS_NAN(TYPE, A) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
- if (isnan (A)) \
|
||||||
|
+ if (isnan (A) && !issignaling (A)) \
|
||||||
|
puts ("PASS: " #TYPE " " #A); \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
@@ -41,6 +43,19 @@
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
+#define CHECK_PAYLOAD(TYPE, FUNC, A, P) \
|
||||||
|
+ do \
|
||||||
|
+ { \
|
||||||
|
+ if (FUNC (&(A)) == (P)) \
|
||||||
|
+ puts ("PASS: " #TYPE " payload " #A); \
|
||||||
|
+ else \
|
||||||
|
+ { \
|
||||||
|
+ puts ("FAIL: " #TYPE " payload " #A); \
|
||||||
|
+ result = 1; \
|
||||||
|
+ } \
|
||||||
|
+ } \
|
||||||
|
+ while (0)
|
||||||
|
+
|
||||||
|
#define CHECK_SAME_NAN(TYPE, A, B) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
@@ -71,7 +86,7 @@
|
||||||
|
bits. */
|
||||||
|
#define CAN_TEST_EQ(MANT_DIG) ((MANT_DIG) != 64 && (MANT_DIG) != 106)
|
||||||
|
|
||||||
|
-#define RUN_TESTS(TYPE, SFUNC, FUNC, MANT_DIG) \
|
||||||
|
+#define RUN_TESTS(TYPE, SFUNC, FUNC, PLFUNC, MANT_DIG) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
TYPE n123 = WRAP_NAN (FUNC, "123"); \
|
||||||
|
@@ -82,6 +97,10 @@
|
||||||
|
CHECK_IS_NAN (TYPE, n456); \
|
||||||
|
TYPE s456 = WRAP_STRTO (SFUNC, "NAN(456)"); \
|
||||||
|
CHECK_IS_NAN (TYPE, s456); \
|
||||||
|
+ TYPE nh123 = WRAP_NAN (FUNC, "0x123"); \
|
||||||
|
+ CHECK_IS_NAN (TYPE, nh123); \
|
||||||
|
+ TYPE sh123 = WRAP_STRTO (SFUNC, "NAN(0x123)"); \
|
||||||
|
+ CHECK_IS_NAN (TYPE, sh123); \
|
||||||
|
TYPE n123x = WRAP_NAN (FUNC, "123)"); \
|
||||||
|
CHECK_IS_NAN (TYPE, n123x); \
|
||||||
|
TYPE nemp = WRAP_NAN (FUNC, ""); \
|
||||||
|
@@ -92,8 +111,16 @@
|
||||||
|
CHECK_IS_NAN (TYPE, sx); \
|
||||||
|
if (CAN_TEST_EQ (MANT_DIG)) \
|
||||||
|
CHECK_SAME_NAN (TYPE, n123, s123); \
|
||||||
|
+ CHECK_PAYLOAD (TYPE, PLFUNC, n123, 123); \
|
||||||
|
+ CHECK_PAYLOAD (TYPE, PLFUNC, s123, 123); \
|
||||||
|
if (CAN_TEST_EQ (MANT_DIG)) \
|
||||||
|
CHECK_SAME_NAN (TYPE, n456, s456); \
|
||||||
|
+ CHECK_PAYLOAD (TYPE, PLFUNC, n456, 456); \
|
||||||
|
+ CHECK_PAYLOAD (TYPE, PLFUNC, s456, 456); \
|
||||||
|
+ if (CAN_TEST_EQ (MANT_DIG)) \
|
||||||
|
+ CHECK_SAME_NAN (TYPE, nh123, sh123); \
|
||||||
|
+ CHECK_PAYLOAD (TYPE, PLFUNC, nh123, 0x123); \
|
||||||
|
+ CHECK_PAYLOAD (TYPE, PLFUNC, sh123, 0x123); \
|
||||||
|
if (CAN_TEST_EQ (MANT_DIG)) \
|
||||||
|
CHECK_SAME_NAN (TYPE, nemp, semp); \
|
||||||
|
if (CAN_TEST_EQ (MANT_DIG)) \
|
||||||
|
@@ -110,9 +137,31 @@ static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
- RUN_TESTS (float, strtof, nanf, FLT_MANT_DIG);
|
||||||
|
- RUN_TESTS (double, strtod, nan, DBL_MANT_DIG);
|
||||||
|
- RUN_TESTS (long double, strtold, nanl, LDBL_MANT_DIG);
|
||||||
|
+ RUN_TESTS (float, strtof, nanf, getpayloadf, FLT_MANT_DIG);
|
||||||
|
+ RUN_TESTS (double, strtod, nan, getpayload, DBL_MANT_DIG);
|
||||||
|
+ RUN_TESTS (long double, strtold, nanl, getpayloadl, LDBL_MANT_DIG);
|
||||||
|
+#if __HAVE_FLOAT16
|
||||||
|
+ RUN_TESTS (_Float16, strtof16, nanf16, getpayloadf16, FLT16_MANT_DIG);
|
||||||
|
+#endif
|
||||||
|
+#if __HAVE_FLOAT32
|
||||||
|
+ RUN_TESTS (_Float32, strtof32, nanf32, getpayloadf32, FLT32_MANT_DIG);
|
||||||
|
+#endif
|
||||||
|
+#if __HAVE_FLOAT64
|
||||||
|
+ RUN_TESTS (_Float64, strtof64, nanf64, getpayloadf64, FLT64_MANT_DIG);
|
||||||
|
+#endif
|
||||||
|
+#if __HAVE_FLOAT128
|
||||||
|
+ RUN_TESTS (_Float128, strtof128, nanf128, getpayloadf128, FLT128_MANT_DIG);
|
||||||
|
+#endif
|
||||||
|
+#if __HAVE_FLOAT32X
|
||||||
|
+ RUN_TESTS (_Float32x, strtof32x, nanf32x, getpayloadf32x, FLT32X_MANT_DIG);
|
||||||
|
+#endif
|
||||||
|
+#if __HAVE_FLOAT64X
|
||||||
|
+ RUN_TESTS (_Float64x, strtof64x, nanf64x, getpayloadf64x, FLT64X_MANT_DIG);
|
||||||
|
+#endif
|
||||||
|
+#if __HAVE_FLOAT128X
|
||||||
|
+ RUN_TESTS (_Float128x, strtof128x, nanf128x, getpayloadf128x,
|
||||||
|
+ FLT128X_MANT_DIG);
|
||||||
|
+#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
147
glibc-RHEL-46739-6.patch
Normal file
147
glibc-RHEL-46739-6.patch
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
commit 64f62c47e9c350f353336f2df6714e1d48ec50d8
|
||||||
|
Author: Joseph Myers <josmyers@redhat.com>
|
||||||
|
Date: Wed Sep 4 13:21:23 2024 +0000
|
||||||
|
|
||||||
|
Do not set errno for overflowing NaN payload in strtod/nan (bug 32045)
|
||||||
|
|
||||||
|
As reported in bug 32045, it's incorrect for strtod/nan functions to
|
||||||
|
set errno based on overflowing payload (strtod should only set errno
|
||||||
|
for overflow / underflow of its actual result, and potentially if
|
||||||
|
nothing in the string can be parsed as a number at all; nan should be
|
||||||
|
a pure function that never sets it). Save and restore errno around
|
||||||
|
the internal strtoull call and add associated test coverage.
|
||||||
|
|
||||||
|
Tested for x86_64.
|
||||||
|
|
||||||
|
diff --git a/math/Makefile b/math/Makefile
|
||||||
|
index 2edb044d9d590de1..a3c44def8acae93b 100644
|
||||||
|
--- a/math/Makefile
|
||||||
|
+++ b/math/Makefile
|
||||||
|
@@ -452,6 +452,7 @@ CFLAGS-test-flt-eval-method.c += -fexcess-precision=standard
|
||||||
|
CFLAGS-test-fe-snans-always-signal.c += -fsignaling-nans
|
||||||
|
|
||||||
|
CFLAGS-test-nan-const.c += -fno-builtin
|
||||||
|
+CFLAGS-test-nan-payload.c += -fno-builtin
|
||||||
|
|
||||||
|
include ../Rules
|
||||||
|
|
||||||
|
diff --git a/math/test-nan-payload.c b/math/test-nan-payload.c
|
||||||
|
index 0ee5432d40a3f997..5f54bf26b6163816 100644
|
||||||
|
--- a/math/test-nan-payload.c
|
||||||
|
+++ b/math/test-nan-payload.c
|
||||||
|
@@ -18,6 +18,7 @@
|
||||||
|
|
||||||
|
#define _LIBC_TEST 1
|
||||||
|
#define __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||||
|
+#include <errno.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
@@ -82,6 +83,26 @@
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
+#define CLEAR_ERRNO \
|
||||||
|
+ do \
|
||||||
|
+ { \
|
||||||
|
+ errno = 12345; \
|
||||||
|
+ } \
|
||||||
|
+ while (0)
|
||||||
|
+
|
||||||
|
+#define CHECK_ERRNO(TYPE, A) \
|
||||||
|
+ do \
|
||||||
|
+ { \
|
||||||
|
+ if (errno == 12345) \
|
||||||
|
+ puts ("PASS: " #TYPE " " #A " errno"); \
|
||||||
|
+ else \
|
||||||
|
+ { \
|
||||||
|
+ puts ("FAIL: " #TYPE " " #A " errno"); \
|
||||||
|
+ 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)
|
||||||
|
@@ -89,26 +110,58 @@
|
||||||
|
#define RUN_TESTS(TYPE, SFUNC, FUNC, PLFUNC, MANT_DIG) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
+ CLEAR_ERRNO; \
|
||||||
|
TYPE n123 = WRAP_NAN (FUNC, "123"); \
|
||||||
|
+ CHECK_ERRNO (TYPE, n123); \
|
||||||
|
CHECK_IS_NAN (TYPE, n123); \
|
||||||
|
+ CLEAR_ERRNO; \
|
||||||
|
TYPE s123 = WRAP_STRTO (SFUNC, "NAN(123)"); \
|
||||||
|
+ CHECK_ERRNO (TYPE, s123); \
|
||||||
|
CHECK_IS_NAN (TYPE, s123); \
|
||||||
|
+ CLEAR_ERRNO; \
|
||||||
|
TYPE n456 = WRAP_NAN (FUNC, "456"); \
|
||||||
|
+ CHECK_ERRNO (TYPE, n456); \
|
||||||
|
CHECK_IS_NAN (TYPE, n456); \
|
||||||
|
+ CLEAR_ERRNO; \
|
||||||
|
TYPE s456 = WRAP_STRTO (SFUNC, "NAN(456)"); \
|
||||||
|
+ CHECK_ERRNO (TYPE, s456); \
|
||||||
|
CHECK_IS_NAN (TYPE, s456); \
|
||||||
|
+ CLEAR_ERRNO; \
|
||||||
|
TYPE nh123 = WRAP_NAN (FUNC, "0x123"); \
|
||||||
|
+ CHECK_ERRNO (TYPE, nh123); \
|
||||||
|
CHECK_IS_NAN (TYPE, nh123); \
|
||||||
|
+ CLEAR_ERRNO; \
|
||||||
|
TYPE sh123 = WRAP_STRTO (SFUNC, "NAN(0x123)"); \
|
||||||
|
+ CHECK_ERRNO (TYPE, sh123); \
|
||||||
|
CHECK_IS_NAN (TYPE, sh123); \
|
||||||
|
+ CLEAR_ERRNO; \
|
||||||
|
TYPE n123x = WRAP_NAN (FUNC, "123)"); \
|
||||||
|
+ CHECK_ERRNO (TYPE, n123x); \
|
||||||
|
CHECK_IS_NAN (TYPE, n123x); \
|
||||||
|
+ CLEAR_ERRNO; \
|
||||||
|
TYPE nemp = WRAP_NAN (FUNC, ""); \
|
||||||
|
+ CHECK_ERRNO (TYPE, nemp); \
|
||||||
|
CHECK_IS_NAN (TYPE, nemp); \
|
||||||
|
+ CLEAR_ERRNO; \
|
||||||
|
TYPE semp = WRAP_STRTO (SFUNC, "NAN()"); \
|
||||||
|
+ CHECK_ERRNO (TYPE, semp); \
|
||||||
|
CHECK_IS_NAN (TYPE, semp); \
|
||||||
|
+ CLEAR_ERRNO; \
|
||||||
|
TYPE sx = WRAP_STRTO (SFUNC, "NAN"); \
|
||||||
|
+ CHECK_ERRNO (TYPE, sx); \
|
||||||
|
CHECK_IS_NAN (TYPE, sx); \
|
||||||
|
+ CLEAR_ERRNO; \
|
||||||
|
+ TYPE novf = WRAP_NAN (FUNC, "9999999999" \
|
||||||
|
+ "99999999999999999999" \
|
||||||
|
+ "9999999999"); \
|
||||||
|
+ CHECK_ERRNO (TYPE, novf); \
|
||||||
|
+ CHECK_IS_NAN (TYPE, novf); \
|
||||||
|
+ CLEAR_ERRNO; \
|
||||||
|
+ TYPE sovf = WRAP_STRTO (SFUNC, "NAN(9999999999" \
|
||||||
|
+ "99999999999999999999" \
|
||||||
|
+ "9999999999)"); \
|
||||||
|
+ CHECK_ERRNO (TYPE, sovf); \
|
||||||
|
+ CHECK_IS_NAN (TYPE, sovf); \
|
||||||
|
if (CAN_TEST_EQ (MANT_DIG)) \
|
||||||
|
CHECK_SAME_NAN (TYPE, n123, s123); \
|
||||||
|
CHECK_PAYLOAD (TYPE, PLFUNC, n123, 123); \
|
||||||
|
diff --git a/stdlib/strtod_nan_main.c b/stdlib/strtod_nan_main.c
|
||||||
|
index ba81355d1c0dbeda..8d7d43818bdba79a 100644
|
||||||
|
--- a/stdlib/strtod_nan_main.c
|
||||||
|
+++ b/stdlib/strtod_nan_main.c
|
||||||
|
@@ -16,6 +16,7 @@
|
||||||
|
License along with the GNU C Library; if not, see
|
||||||
|
<https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
+#include <errno.h>
|
||||||
|
#include <ieee754.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <math.h>
|
||||||
|
@@ -50,7 +51,9 @@ STRTOD_NAN (const STRING_TYPE *str, STRING_TYPE **endptr, STRING_TYPE endc)
|
||||||
|
STRING_TYPE *endp;
|
||||||
|
unsigned long long int mant;
|
||||||
|
|
||||||
|
+ int save_errno = errno;
|
||||||
|
mant = STRTOULL (str, &endp, 0);
|
||||||
|
+ __set_errno (save_errno);
|
||||||
|
if (endp == cp)
|
||||||
|
SET_NAN_PAYLOAD (retval, mant);
|
||||||
|
|
76
glibc-RHEL-46739-7.patch
Normal file
76
glibc-RHEL-46739-7.patch
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
commit cc3e743fc09ee6fca45767629df9cbcbe1feba82
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Sep 5 21:18:23 2024 +0200
|
||||||
|
|
||||||
|
powerpc64le: Build new strtod tests with long double ABI flags (bug 32145)
|
||||||
|
|
||||||
|
This fixes several test failures:
|
||||||
|
|
||||||
|
=====FAIL: stdlib/tst-strtod1i.out=====
|
||||||
|
Locale tests
|
||||||
|
all OK
|
||||||
|
Locale tests
|
||||||
|
all OK
|
||||||
|
Locale tests
|
||||||
|
strtold("1,5") returns -6,38643e+367 and not 1,5
|
||||||
|
strtold("1.5") returns 1,5 and not 1
|
||||||
|
strtold("1.500") returns 1 and not 1500
|
||||||
|
strtold("36.893.488.147.419.103.232") returns 1500 and not 3,68935e+19
|
||||||
|
Locale tests
|
||||||
|
all OK
|
||||||
|
|
||||||
|
=====FAIL: stdlib/tst-strtod3.out=====
|
||||||
|
0: got wrong results -2.5937e+4826, expected 0
|
||||||
|
|
||||||
|
=====FAIL: stdlib/tst-strtod4.out=====
|
||||||
|
0: got wrong results -6,38643e+367, expected 0
|
||||||
|
1: got wrong results 0, expected 1e+06
|
||||||
|
2: got wrong results 1e+06, expected 10
|
||||||
|
|
||||||
|
=====FAIL: stdlib/tst-strtod5i.out=====
|
||||||
|
0: got wrong results -6,38643e+367, expected 0
|
||||||
|
2: got wrong results 0, expected -0
|
||||||
|
4: got wrong results -0, expected 0
|
||||||
|
5: got wrong results 0, expected -0
|
||||||
|
6: got wrong results -0, expected 0
|
||||||
|
7: got wrong results 0, expected -0
|
||||||
|
8: got wrong results -0, expected 0
|
||||||
|
9: got wrong results 0, expected -0
|
||||||
|
10: got wrong results -0, expected 0
|
||||||
|
11: got wrong results 0, expected -0
|
||||||
|
12: got wrong results -0, expected 0
|
||||||
|
13: got wrong results 0, expected -0
|
||||||
|
14: got wrong results -0, expected 0
|
||||||
|
15: got wrong results 0, expected -0
|
||||||
|
16: got wrong results -0, expected 0
|
||||||
|
17: got wrong results 0, expected -0
|
||||||
|
18: got wrong results -0, expected 0
|
||||||
|
20: got wrong results 0, expected -0
|
||||||
|
22: got wrong results -0, expected 0
|
||||||
|
23: got wrong results 0, expected -0
|
||||||
|
24: got wrong results -0, expected 0
|
||||||
|
25: got wrong results 0, expected -0
|
||||||
|
26: got wrong results -0, expected 0
|
||||||
|
27: got wrong results 0, expected -0
|
||||||
|
|
||||||
|
Fixes commit 3fc063dee01da4f80920a14b7db637c8501d6fd4
|
||||||
|
("Make __strtod_internal tests type-generic").
|
||||||
|
|
||||||
|
Suggested-by: Joseph Myers <josmyers@redhat.com>
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/sysdeps/powerpc/powerpc64/le/Makefile b/sysdeps/powerpc/powerpc64/le/Makefile
|
||||||
|
index 7c036b45fcc0d7f9..8bc71fd18d3f1edc 100644
|
||||||
|
--- a/sysdeps/powerpc/powerpc64/le/Makefile
|
||||||
|
+++ b/sysdeps/powerpc/powerpc64/le/Makefile
|
||||||
|
@@ -128,6 +128,10 @@ CFLAGS-tst-strtod-round.c += $(type-float128-CFLAGS)
|
||||||
|
CFLAGS-tst-wcstod-round.c += $(type-float128-CFLAGS)
|
||||||
|
CFLAGS-tst-strtod-nan-locale.c += $(type-float128-CFLAGS)
|
||||||
|
CFLAGS-tst-wcstod-nan-locale.c += $(type-float128-CFLAGS)
|
||||||
|
+CFLAGS-tst-strtod1i.c += $(type-float128-CFLAGS)
|
||||||
|
+CFLAGS-tst-strtod3.c += $(type-float128-CFLAGS)
|
||||||
|
+CFLAGS-tst-strtod4.c += $(type-float128-CFLAGS)
|
||||||
|
+CFLAGS-tst-strtod5i.c += $(type-float128-CFLAGS)
|
||||||
|
CFLAGS-tst-strtod6.c += $(type-float128-CFLAGS)
|
||||||
|
CFLAGS-tst-strfrom.c += $(type-float128-CFLAGS)
|
||||||
|
CFLAGS-tst-strfrom-locale.c += $(type-float128-CFLAGS)
|
254
glibc-RHEL-46739-8.patch
Normal file
254
glibc-RHEL-46739-8.patch
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
commit 8de031bcb9adfa736c0caed2c79d10947b8d8f48
|
||||||
|
Author: Joseph Myers <josmyers@redhat.com>
|
||||||
|
Date: Fri Sep 20 23:23:13 2024 +0000
|
||||||
|
|
||||||
|
Make tst-strtod2 and tst-strtod5 type-generic
|
||||||
|
|
||||||
|
Some of the strtod tests use type-generic machinery in tst-strtod.h to
|
||||||
|
test the strto* functions for all floating types, while others only
|
||||||
|
test double even when the tests are in fact meaningful for all
|
||||||
|
floating types.
|
||||||
|
|
||||||
|
Convert tst-strtod2 and tst-strtod5 to use the type-generic machinery
|
||||||
|
so they test all floating types. I haven't tried to convert them to
|
||||||
|
use newer test interfaces in other ways, just made the changes
|
||||||
|
necessary to use the type-generic machinery.
|
||||||
|
|
||||||
|
Tested for x86_64.
|
||||||
|
|
||||||
|
diff --git a/stdlib/tst-strtod2.c b/stdlib/tst-strtod2.c
|
||||||
|
index a7df82ebbde14c5f..2cb0953fa911efd0 100644
|
||||||
|
--- a/stdlib/tst-strtod2.c
|
||||||
|
+++ b/stdlib/tst-strtod2.c
|
||||||
|
@@ -1,43 +1,61 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
-struct test
|
||||||
|
-{
|
||||||
|
- const char *str;
|
||||||
|
- double result;
|
||||||
|
- size_t offset;
|
||||||
|
-} tests[] =
|
||||||
|
-{
|
||||||
|
- { "0xy", 0.0, 1 },
|
||||||
|
- { "0x.y", 0.0, 1 },
|
||||||
|
- { "0x0.y", 0.0, 4 },
|
||||||
|
- { "0x.0y", 0.0, 4 },
|
||||||
|
- { ".y", 0.0, 0 },
|
||||||
|
- { "0.y", 0.0, 2 },
|
||||||
|
- { ".0y", 0.0, 2 }
|
||||||
|
-};
|
||||||
|
+#include "tst-strtod.h"
|
||||||
|
+
|
||||||
|
+#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
|
||||||
|
+struct test_strto ## FSUF \
|
||||||
|
+{ \
|
||||||
|
+ const char *str; \
|
||||||
|
+ FTYPE result; \
|
||||||
|
+ size_t offset; \
|
||||||
|
+} tests_strto ## FSUF[] = \
|
||||||
|
+{ \
|
||||||
|
+ { "0xy", 0.0 ## LSUF, 1 }, \
|
||||||
|
+ { "0x.y", 0.0 ## LSUF, 1 }, \
|
||||||
|
+ { "0x0.y", 0.0 ## LSUF, 4 }, \
|
||||||
|
+ { "0x.0y", 0.0 ## LSUF, 4 }, \
|
||||||
|
+ { ".y", 0.0 ## LSUF, 0 }, \
|
||||||
|
+ { "0.y", 0.0 ## LSUF, 2 }, \
|
||||||
|
+ { ".0y", 0.0 ## LSUF, 2 } \
|
||||||
|
+}; \
|
||||||
|
+ \
|
||||||
|
+static int \
|
||||||
|
+test_strto ## FSUF (void) \
|
||||||
|
+{ \
|
||||||
|
+ int status = 0; \
|
||||||
|
+ for (size_t i = 0; \
|
||||||
|
+ i < sizeof (tests_strto ## FSUF) / sizeof (tests_strto ## FSUF[0]); \
|
||||||
|
+ ++i) \
|
||||||
|
+ { \
|
||||||
|
+ char *ep; \
|
||||||
|
+ FTYPE r = strto ## FSUF (tests_strto ## FSUF[i].str, &ep); \
|
||||||
|
+ if (r != tests_strto ## FSUF[i].result) \
|
||||||
|
+ { \
|
||||||
|
+ char buf1[FSTRLENMAX], buf2[FSTRLENMAX]; \
|
||||||
|
+ FTOSTR (buf1, sizeof (buf1), "%g", r); \
|
||||||
|
+ FTOSTR (buf2, sizeof (buf2), "%g", tests_strto ## FSUF[i].result); \
|
||||||
|
+ printf ("test %zu r = %s, expect %s\n", i, buf1, buf2); \
|
||||||
|
+ status = 1; \
|
||||||
|
+ } \
|
||||||
|
+ if (ep != tests_strto ## FSUF[i].str + tests_strto ## FSUF[i].offset) \
|
||||||
|
+ { \
|
||||||
|
+ printf ("test %zu strto" #FSUF \
|
||||||
|
+ " parsed %tu characters, expected %zu\n", \
|
||||||
|
+ i, ep - tests_strto ## FSUF[i].str, \
|
||||||
|
+ tests_strto ## FSUF[i].offset); \
|
||||||
|
+ status = 1; \
|
||||||
|
+ } \
|
||||||
|
+ } \
|
||||||
|
+ return status; \
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+GEN_TEST_STRTOD_FOREACH (TEST_STRTOD)
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
- int status = 0;
|
||||||
|
- for (size_t i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
|
||||||
|
- {
|
||||||
|
- char *ep;
|
||||||
|
- double r = strtod (tests[i].str, &ep);
|
||||||
|
- if (r != tests[i].result)
|
||||||
|
- {
|
||||||
|
- printf ("test %zu r = %g, expect %g\n", i, r, tests[i].result);
|
||||||
|
- status = 1;
|
||||||
|
- }
|
||||||
|
- if (ep != tests[i].str + tests[i].offset)
|
||||||
|
- {
|
||||||
|
- printf ("test %zu strtod parsed %tu characters, expected %zu\n",
|
||||||
|
- i, ep - tests[i].str, tests[i].offset);
|
||||||
|
- status = 1;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- return status;
|
||||||
|
+ return STRTOD_TEST_FOREACH (test_strto);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_FUNCTION do_test ()
|
||||||
|
diff --git a/stdlib/tst-strtod5.c b/stdlib/tst-strtod5.c
|
||||||
|
index be091ec1b9f87394..005b3480a76955da 100644
|
||||||
|
--- a/stdlib/tst-strtod5.c
|
||||||
|
+++ b/stdlib/tst-strtod5.c
|
||||||
|
@@ -22,35 +22,75 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
+#include "tst-strtod.h"
|
||||||
|
+
|
||||||
|
#define NBSP "\xc2\xa0"
|
||||||
|
|
||||||
|
-static const struct
|
||||||
|
-{
|
||||||
|
- const char *in;
|
||||||
|
- double expected;
|
||||||
|
-} tests[] =
|
||||||
|
- {
|
||||||
|
- { "0", 0.0 },
|
||||||
|
- { "000", 0.0 },
|
||||||
|
- { "-0", -0.0 },
|
||||||
|
- { "-000", -0.0 },
|
||||||
|
- { "0,", 0.0 },
|
||||||
|
- { "-0,", -0.0 },
|
||||||
|
- { "0,0", 0.0 },
|
||||||
|
- { "-0,0", -0.0 },
|
||||||
|
- { "0e-10", 0.0 },
|
||||||
|
- { "-0e-10", -0.0 },
|
||||||
|
- { "0,e-10", 0.0 },
|
||||||
|
- { "-0,e-10", -0.0 },
|
||||||
|
- { "0,0e-10", 0.0 },
|
||||||
|
- { "-0,0e-10", -0.0 },
|
||||||
|
- { "0e-1000000", 0.0 },
|
||||||
|
- { "-0e-1000000", -0.0 },
|
||||||
|
- { "0,0e-1000000", 0.0 },
|
||||||
|
- { "-0,0e-1000000", -0.0 },
|
||||||
|
- };
|
||||||
|
-#define NTESTS (sizeof (tests) / sizeof (tests[0]))
|
||||||
|
+#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
|
||||||
|
+static const struct \
|
||||||
|
+{ \
|
||||||
|
+ const char *in; \
|
||||||
|
+ FTYPE expected; \
|
||||||
|
+} tests_strto ## FSUF[] = \
|
||||||
|
+ { \
|
||||||
|
+ { "0", 0.0 ## LSUF }, \
|
||||||
|
+ { "000", 0.0 ## LSUF }, \
|
||||||
|
+ { "-0", -0.0 ## LSUF }, \
|
||||||
|
+ { "-000", -0.0 ## LSUF }, \
|
||||||
|
+ { "0,", 0.0 ## LSUF }, \
|
||||||
|
+ { "-0,", -0.0 ## LSUF }, \
|
||||||
|
+ { "0,0", 0.0 ## LSUF }, \
|
||||||
|
+ { "-0,0", -0.0 ## LSUF }, \
|
||||||
|
+ { "0e-10", 0.0 ## LSUF }, \
|
||||||
|
+ { "-0e-10", -0.0 ## LSUF }, \
|
||||||
|
+ { "0,e-10", 0.0 ## LSUF }, \
|
||||||
|
+ { "-0,e-10", -0.0 ## LSUF }, \
|
||||||
|
+ { "0,0e-10", 0.0 ## LSUF }, \
|
||||||
|
+ { "-0,0e-10", -0.0 ## LSUF }, \
|
||||||
|
+ { "0e-1000000", 0.0 ## LSUF }, \
|
||||||
|
+ { "-0e-1000000", -0.0 ## LSUF }, \
|
||||||
|
+ { "0,0e-1000000", 0.0 ## LSUF }, \
|
||||||
|
+ { "-0,0e-1000000", -0.0 ## LSUF }, \
|
||||||
|
+ }; \
|
||||||
|
+ \
|
||||||
|
+ \
|
||||||
|
+static int \
|
||||||
|
+test_strto ## FSUF (void) \
|
||||||
|
+{ \
|
||||||
|
+ int status = 0; \
|
||||||
|
+ \
|
||||||
|
+ for (int i = 0; \
|
||||||
|
+ i < sizeof (tests_strto ## FSUF) / sizeof (tests_strto ## FSUF[0]); \
|
||||||
|
+ ++i) \
|
||||||
|
+ { \
|
||||||
|
+ char *ep; \
|
||||||
|
+ FTYPE r = strto ## FSUF (tests_strto ## FSUF[i].in, &ep); \
|
||||||
|
+ \
|
||||||
|
+ if (*ep != '\0') \
|
||||||
|
+ { \
|
||||||
|
+ printf ("%d: got rest string \"%s\", expected \"\"\n", i, ep); \
|
||||||
|
+ status = 1; \
|
||||||
|
+ } \
|
||||||
|
+ \
|
||||||
|
+ if (r != tests_strto ## FSUF[i].expected \
|
||||||
|
+ || (copysign ## CSUF (10.0 ## LSUF, r) \
|
||||||
|
+ != copysign ## CSUF (10.0 ## LSUF, \
|
||||||
|
+ tests_strto ## FSUF[i].expected))) \
|
||||||
|
+ { \
|
||||||
|
+ char buf1[FSTRLENMAX], buf2[FSTRLENMAX]; \
|
||||||
|
+ FTOSTR (buf1, sizeof (buf1), "%g", r); \
|
||||||
|
+ FTOSTR (buf2, sizeof (buf2), "%g", \
|
||||||
|
+ tests_strto ## FSUF[i].expected); \
|
||||||
|
+ printf ("%d: got wrong results %s, expected %s\n", \
|
||||||
|
+ i, buf1, buf2); \
|
||||||
|
+ status = 1; \
|
||||||
|
+ } \
|
||||||
|
+ } \
|
||||||
|
+ \
|
||||||
|
+ return status; \
|
||||||
|
+}
|
||||||
|
|
||||||
|
+GEN_TEST_STRTOD_FOREACH (TEST_STRTOD)
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
@@ -61,29 +101,7 @@ do_test (void)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- int status = 0;
|
||||||
|
-
|
||||||
|
- for (int i = 0; i < NTESTS; ++i)
|
||||||
|
- {
|
||||||
|
- char *ep;
|
||||||
|
- double r = strtod (tests[i].in, &ep);
|
||||||
|
-
|
||||||
|
- if (*ep != '\0')
|
||||||
|
- {
|
||||||
|
- printf ("%d: got rest string \"%s\", expected \"\"\n", i, ep);
|
||||||
|
- status = 1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (r != tests[i].expected
|
||||||
|
- || copysign (10.0, r) != copysign (10.0, tests[i].expected))
|
||||||
|
- {
|
||||||
|
- printf ("%d: got wrong results %g, expected %g\n",
|
||||||
|
- i, r, tests[i].expected);
|
||||||
|
- status = 1;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return status;
|
||||||
|
+ return STRTOD_TEST_FOREACH (test_strto);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <support/test-driver.c>
|
79
glibc-RHEL-46739-9.patch
Normal file
79
glibc-RHEL-46739-9.patch
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
commit b5d3737b305525315e0c7c93ca49eadc868eabd5
|
||||||
|
Author: Joseph Myers <josmyers@redhat.com>
|
||||||
|
Date: Fri Sep 20 23:24:02 2024 +0000
|
||||||
|
|
||||||
|
Add more tests of strtod end pointer
|
||||||
|
|
||||||
|
Although there are some tests in tst-strtod2 and tst-strtod3 for the
|
||||||
|
end pointer provided by strtod when it doesn't parse the whole string,
|
||||||
|
they aren't very thorough. Add tests of more such cases to
|
||||||
|
tst-strtod2.
|
||||||
|
|
||||||
|
Tested for x86_64.
|
||||||
|
|
||||||
|
diff --git a/stdlib/tst-strtod2.c b/stdlib/tst-strtod2.c
|
||||||
|
index 2cb0953fa911efd0..c84bd792c1a3f511 100644
|
||||||
|
--- a/stdlib/tst-strtod2.c
|
||||||
|
+++ b/stdlib/tst-strtod2.c
|
||||||
|
@@ -1,3 +1,4 @@
|
||||||
|
+#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
@@ -17,10 +18,46 @@ struct test_strto ## FSUF \
|
||||||
|
{ "0x.0y", 0.0 ## LSUF, 4 }, \
|
||||||
|
{ ".y", 0.0 ## LSUF, 0 }, \
|
||||||
|
{ "0.y", 0.0 ## LSUF, 2 }, \
|
||||||
|
- { ".0y", 0.0 ## LSUF, 2 } \
|
||||||
|
+ { ".0y", 0.0 ## LSUF, 2 }, \
|
||||||
|
+ { "1.0e", 1.0 ## LSUF, 3 }, \
|
||||||
|
+ { "1.0e+", 1.0 ## LSUF, 3 }, \
|
||||||
|
+ { "1.0e-", 1.0 ## LSUF, 3 }, \
|
||||||
|
+ { "1.0ex", 1.0 ## LSUF, 3 }, \
|
||||||
|
+ { "1.0e+x", 1.0 ## LSUF, 3 }, \
|
||||||
|
+ { "1.0e-x", 1.0 ## LSUF, 3 }, \
|
||||||
|
+ { "0x1p", 1.0 ## LSUF, 3 }, \
|
||||||
|
+ { "0x1p+", 1.0 ## LSUF, 3 }, \
|
||||||
|
+ { "0x1p-", 1.0 ## LSUF, 3 }, \
|
||||||
|
+ { "0x1px", 1.0 ## LSUF, 3 }, \
|
||||||
|
+ { "0x1p+x", 1.0 ## LSUF, 3 }, \
|
||||||
|
+ { "0x1p-x", 1.0 ## LSUF, 3 }, \
|
||||||
|
+ { "INFx", INFINITY, 3 }, \
|
||||||
|
+ { "infx", INFINITY, 3 }, \
|
||||||
|
+ { "INFINITx", INFINITY, 3 }, \
|
||||||
|
+ { "infinitx", INFINITY, 3 }, \
|
||||||
|
+ { "INFINITYY", INFINITY, 8 }, \
|
||||||
|
+ { "infinityy", INFINITY, 8 }, \
|
||||||
|
+ { "NANx", NAN, 3 }, \
|
||||||
|
+ { "nanx", NAN, 3 }, \
|
||||||
|
+ { "NAN(", NAN, 3 }, \
|
||||||
|
+ { "nan(", NAN, 3 }, \
|
||||||
|
+ { "NAN(x", NAN, 3 }, \
|
||||||
|
+ { "nan(x", NAN, 3 }, \
|
||||||
|
+ { "NAN(x)y", NAN, 6 }, \
|
||||||
|
+ { "nan(x)y", NAN, 6 }, \
|
||||||
|
+ { "NAN(*)y", NAN, 3 }, \
|
||||||
|
+ { "nan(*)y", NAN, 3 } \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
static int \
|
||||||
|
+compare_strto ## FSUF (FTYPE x, FTYPE y) \
|
||||||
|
+{ \
|
||||||
|
+ if (isnan (x) && isnan (y)) \
|
||||||
|
+ return 1; \
|
||||||
|
+ return x == y; \
|
||||||
|
+} \
|
||||||
|
+ \
|
||||||
|
+static int \
|
||||||
|
test_strto ## FSUF (void) \
|
||||||
|
{ \
|
||||||
|
int status = 0; \
|
||||||
|
@@ -30,7 +67,7 @@ test_strto ## FSUF (void) \
|
||||||
|
{ \
|
||||||
|
char *ep; \
|
||||||
|
FTYPE r = strto ## FSUF (tests_strto ## FSUF[i].str, &ep); \
|
||||||
|
- if (r != tests_strto ## FSUF[i].result) \
|
||||||
|
+ if (!compare_strto ## FSUF (r, tests_strto ## FSUF[i].result)) \
|
||||||
|
{ \
|
||||||
|
char buf1[FSTRLENMAX], buf2[FSTRLENMAX]; \
|
||||||
|
FTOSTR (buf1, sizeof (buf1), "%g", r); \
|
17
glibc.spec
17
glibc.spec
@ -157,7 +157,7 @@ end \
|
|||||||
Summary: The GNU libc libraries
|
Summary: The GNU libc libraries
|
||||||
Name: glibc
|
Name: glibc
|
||||||
Version: %{glibcversion}
|
Version: %{glibcversion}
|
||||||
Release: 132%{?dist}
|
Release: 133%{?dist}
|
||||||
|
|
||||||
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
|
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
|
||||||
# libraries.
|
# libraries.
|
||||||
@ -878,6 +878,17 @@ Patch639: glibc-RHEL-46734.patch
|
|||||||
Patch640: glibc-RHEL-46735.patch
|
Patch640: glibc-RHEL-46735.patch
|
||||||
Patch641: glibc-RHEL-60466-1.patch
|
Patch641: glibc-RHEL-60466-1.patch
|
||||||
Patch642: glibc-RHEL-60466-2.patch
|
Patch642: glibc-RHEL-60466-2.patch
|
||||||
|
Patch643: glibc-RHEL-46739-1.patch
|
||||||
|
Patch644: glibc-RHEL-46739-2.patch
|
||||||
|
Patch645: glibc-RHEL-46739-3.patch
|
||||||
|
Patch646: glibc-RHEL-46739-4.patch
|
||||||
|
Patch647: glibc-RHEL-46739-5.patch
|
||||||
|
Patch648: glibc-RHEL-46739-6.patch
|
||||||
|
Patch649: glibc-RHEL-46739-7.patch
|
||||||
|
Patch650: glibc-RHEL-46739-8.patch
|
||||||
|
Patch651: glibc-RHEL-46739-9.patch
|
||||||
|
Patch652: glibc-RHEL-46739-10.patch
|
||||||
|
Patch653: glibc-RHEL-46739-11.patch
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# Continued list of core "glibc" package information:
|
# Continued list of core "glibc" package information:
|
||||||
@ -3037,6 +3048,10 @@ update_gconv_modules_cache ()
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Mon Sep 30 2024 Arjun Shankar <arjun@redhat.com> - 2.34-133
|
||||||
|
- strtod: Fix subnormal rounding; do not set errno upon overflowing payload;
|
||||||
|
and add several new tests (RHEL-46739)
|
||||||
|
|
||||||
* Fri Sep 27 2024 Florian Weimer <fweimer@redhat.com> - 2.34-132
|
* Fri Sep 27 2024 Florian Weimer <fweimer@redhat.com> - 2.34-132
|
||||||
- Remove some unused ppc64le string functions (RHEL-60466)
|
- Remove some unused ppc64le string functions (RHEL-60466)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user