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 | ||||
| Name: glibc | ||||
| Version: %{glibcversion} | ||||
| Release: 132%{?dist} | ||||
| Release: 133%{?dist} | ||||
| 
 | ||||
| # In general, GPLv2+ is used by programs, LGPLv2+ is used for | ||||
| # libraries. | ||||
| @ -878,6 +878,17 @@ Patch639: glibc-RHEL-46734.patch | ||||
| Patch640: glibc-RHEL-46735.patch | ||||
| Patch641: glibc-RHEL-60466-1.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: | ||||
| @ -3037,6 +3048,10 @@ update_gconv_modules_cache () | ||||
| %endif | ||||
| 
 | ||||
| %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 | ||||
| - Remove some unused ppc64le string functions (RHEL-60466) | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user