]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Do not set errno for overflowing NaN payload in strtod/nan (bug 32045)
authorJoseph Myers <josmyers@redhat.com>
Wed, 4 Sep 2024 13:21:23 +0000 (13:21 +0000)
committerJoseph Myers <josmyers@redhat.com>
Wed, 4 Sep 2024 13:21:23 +0000 (13:21 +0000)
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.

math/Makefile
math/test-nan-payload.c
stdlib/strtod_nan_main.c

index f06d370383d560eaced5d26ec2b75e96f71d3615..b64c3eedd563fd91d56fa83663ccdd617dc578c1 100644 (file)
@@ -1077,6 +1077,7 @@ CFLAGS-test-flt-eval-method.c += -fexcess-precision=standard
 CFLAGS-test-fe-snans-always-signal.c += $(config-cflags-signaling-nans)
 
 CFLAGS-test-nan-const.c += -fno-builtin
+CFLAGS-test-nan-payload.c += -fno-builtin
 
 CFLAGS-test-ceil-except-2.c += -fno-builtin
 CFLAGS-test-floor-except-2.c += -fno-builtin
index 55c13de14eb6a4d0e4453d4bf9fae788fcaf6b80..413791e09f8b348ded5f9c9486a6cfb2eb30b1c5 100644 (file)
@@ -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>
     }                                                  \
   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)
 #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);          \
index 4cb286d2b3fb0676dce0674b295f66e528a81e9b..39fb7e9f75bc5dbd5003632dbe562d180b01c053 100644 (file)
@@ -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);