]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix special case for C2x strtol binary constant handling (BZ# 30371)
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Thu, 25 May 2023 11:14:37 +0000 (08:14 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Thu, 25 May 2023 12:28:23 +0000 (09:28 -0300)
When the base is 0 or 2 and the first two characters are '0' and 'b',
but the rest are no binary digits.  In this case this is no error,
and strtol must return 0 and ENDPTR points to the 'x' or 'b'.

Checked on x86_64-linux-gnu and i686-linux-gnu.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
stdlib/strtol_l.c
stdlib/tst-strtol-binary-c11.c
stdlib/tst-strtol-binary-c2x.c
stdlib/tst-strtol-binary-gnu11.c
stdlib/tst-strtol-binary-gnu2x.c
stdlib/tst-strtol-binary-main.c
wcsmbs/tst-wcstol-binary-c11.c
wcsmbs/tst-wcstol-binary-c2x.c
wcsmbs/tst-wcstol-binary-gnu11.c
wcsmbs/tst-wcstol-binary-gnu2x.c

index 3424c3feab9ec42d59828e3fc0dd625432d7435b..548b46aa52e80784d40e207846671ea2983cd18b 100644 (file)
@@ -526,11 +526,15 @@ INTERNAL (__strtol_l) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
 noconv:
   /* We must handle a special case here: the base is 0 or 16 and the
      first two characters are '0' and 'x', but the rest are no
-     hexadecimal digits.  This is no error case.  We return 0 and
-     ENDPTR points to the `x`.  */
+     hexadecimal digits.  Likewise when the base is 0 or 2 and the
+     first two characters are '0' and 'b', but the rest are no binary
+     digits.  This is no error case.  We return 0 and ENDPTR points to
+     the 'x' or 'b'.  */
   if (endptr != NULL)
     {
-      if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
+      if (save - nptr >= 2
+         && (TOUPPER (save[-1]) == L_('X')
+             || (bin_cst && TOUPPER (save[-1]) == L_('B')))
          && save[-2] == L_('0'))
        *endptr = (STRING_TYPE *) &save[-1];
       else
index 6e58bb25991b31e30f82c57e366572fd5df76172..8b8c31cdd04b066347b3321b484d64fee4a94323 100644 (file)
@@ -20,6 +20,7 @@
 #undef _GNU_SOURCE
 
 #define CHAR char
+#define WIDE 0
 #define FNPFX strto
 #define L_(C) C
 #define TEST_C2X 0
index b9ccfda759e3b6c4af388d63e78e66faaeb82112..e75f0881b698bf2bf3a25513247684ea0b42355d 100644 (file)
@@ -23,6 +23,7 @@
 #define _ISOC2X_SOURCE
 
 #define CHAR char
+#define WIDE 0
 #define FNPFX strto
 #define L_(C) C
 #define TEST_C2X 1
index a029591c8bf71d1ad23524f8c5669fcaf79398e7..7dc81317dfd253e9685a1c0575e8ef26a5b05943 100644 (file)
@@ -25,6 +25,7 @@
 #define __GLIBC_USE_C2X_STRTOL 0
 
 #define CHAR char
+#define WIDE 0
 #define FNPFX strto
 #define L_(C) C
 #define TEST_C2X 0
index 0a7fdd4d4d703a5e18ce62087e3ba5221449c398..96db2414b956b282d3ce9569867e5fc2f3c6bbac 100644 (file)
@@ -18,6 +18,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #define CHAR char
+#define WIDE 0
 #define FNPFX strto
 #define L_(C) C
 #define TEST_C2X 1
index ece310029820a1830c0e5b4611bde657b54a9ae4..54cda5cd035c5e324e16317caae978342291d590 100644 (file)
@@ -21,6 +21,7 @@
 #include <locale.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <wchar.h>
 
 #include <support/check.h>
 #define CONCAT(X, Y) CONCAT_ (X, Y)
 #define FNX(FN) CONCAT (FNPFX, FN)
 
-#define CHECK_RES(ARG, RES, EP, EXPECTED)                              \
+#if WIDE
+# define STRCHR wcschr
+#else
+# define STRCHR strchr
+#endif
+
+#define CHECK_RES(ARG, RES, EP, EXPECTED, EXPECTED_EP)                 \
   do                                                                   \
     {                                                                  \
       if (TEST_C2X)                                                    \
        {                                                               \
          TEST_COMPARE ((RES), EXPECTED);                               \
-         TEST_COMPARE (*(EP), 0);                                      \
+         TEST_VERIFY ((EP) == EXPECTED_EP);                            \
        }                                                               \
       else                                                             \
        {                                                               \
   while (0)
 
 static void
-one_check (const CHAR *s, long int expected_l, unsigned long int expected_ul,
-          long long int expected_ll, unsigned long long int expected_ull)
+one_check (const CHAR *s, const CHAR *expected_p, long int expected_l,
+          unsigned long int expected_ul, long long int expected_ll,
+          unsigned long long int expected_ull)
 {
+  expected_p = expected_p == NULL ? STRCHR (s, '\0') : expected_p;
+
   CHAR *ep;
   long int ret_l;
   unsigned long int ret_ul;
   long long int ret_ll;
   unsigned long long int ret_ull;
   ret_l = FNX (l) (s, &ep, 0);
-  CHECK_RES (s, ret_l, ep, expected_l);
+  CHECK_RES (s, ret_l, ep, expected_l, expected_p);
   ret_l = FNX (l) (s, &ep, 2);
-  CHECK_RES (s, ret_l, ep, expected_l);
+  CHECK_RES (s, ret_l, ep, expected_l, expected_p);
   ret_ul = FNX (ul) (s, &ep, 0);
-  CHECK_RES (s, ret_ul, ep, expected_ul);
+  CHECK_RES (s, ret_ul, ep, expected_ul, expected_p);
   ret_ul = FNX (ul) (s, &ep, 2);
-  CHECK_RES (s, ret_ul, ep, expected_ul);
+  CHECK_RES (s, ret_ul, ep, expected_ul, expected_p);
   ret_ll = FNX (ll) (s, &ep, 0);
-  CHECK_RES (s, ret_ll, ep, expected_ll);
+  CHECK_RES (s, ret_ll, ep, expected_ll, expected_p);
   ret_ll = FNX (ll) (s, &ep, 2);
-  CHECK_RES (s, ret_ll, ep, expected_ll);
+  CHECK_RES (s, ret_ll, ep, expected_ll, expected_p);
   ret_ull = FNX (ull) (s, &ep, 0);
-  CHECK_RES (s, ret_ull, ep, expected_ull);
+  CHECK_RES (s, ret_ull, ep, expected_ull, expected_p);
   ret_ull = FNX (ull) (s, &ep, 2);
-  CHECK_RES (s, ret_ull, ep, expected_ull);
+  CHECK_RES (s, ret_ull, ep, expected_ull, expected_p);
   ret_ll = FNX (imax) (s, &ep, 0);
-  CHECK_RES (s, ret_ll, ep, expected_ll);
+  CHECK_RES (s, ret_ll, ep, expected_ll, expected_p);
   ret_ll = FNX (imax) (s, &ep, 2);
-  CHECK_RES (s, ret_ll, ep, expected_ll);
+  CHECK_RES (s, ret_ll, ep, expected_ll, expected_p);
   ret_ull = FNX (umax) (s, &ep, 0);
-  CHECK_RES (s, ret_ull, ep, expected_ull);
+  CHECK_RES (s, ret_ull, ep, expected_ull, expected_p);
   ret_ull = FNX (umax) (s, &ep, 2);
-  CHECK_RES (s, ret_ull, ep, expected_ull);
+  CHECK_RES (s, ret_ull, ep, expected_ull, expected_p);
 #if TEST_Q
   ret_ll = FNX (q) (s, &ep, 0);
-  CHECK_RES (s, ret_ll, ep, expected_ll);
+  CHECK_RES (s, ret_ll, ep, expected_ll, expected_p);
   ret_ll = FNX (q) (s, &ep, 2);
-  CHECK_RES (s, ret_ll, ep, expected_ll);
+  CHECK_RES (s, ret_ll, ep, expected_ll, expected_p);
   ret_ull = FNX (uq) (s, &ep, 0);
-  CHECK_RES (s, ret_ull, ep, expected_ull);
+  CHECK_RES (s, ret_ull, ep, expected_ull, expected_p);
   ret_ull = FNX (uq) (s, &ep, 2);
-  CHECK_RES (s, ret_ull, ep, expected_ull);
+  CHECK_RES (s, ret_ull, ep, expected_ull, expected_p);
 #endif
 #if TEST_LOCALE
   locale_t loc = xnewlocale (LC_NUMERIC_MASK, "C", (locale_t) 0);
   ret_l = FNX (l_l) (s, &ep, 0, loc);
-  CHECK_RES (s, ret_l, ep, expected_l);
+  CHECK_RES (s, ret_l, ep, expected_l, expected_p);
   ret_l = FNX (l_l) (s, &ep, 2, loc);
-  CHECK_RES (s, ret_l, ep, expected_l);
+  CHECK_RES (s, ret_l, ep, expected_l, expected_p);
   ret_ul = FNX (ul_l) (s, &ep, 0, loc);
-  CHECK_RES (s, ret_ul, ep, expected_ul);
+  CHECK_RES (s, ret_ul, ep, expected_ul, expected_p);
   ret_ul = FNX (ul_l) (s, &ep, 2, loc);
-  CHECK_RES (s, ret_ul, ep, expected_ul);
+  CHECK_RES (s, ret_ul, ep, expected_ul, expected_p);
   ret_ll = FNX (ll_l) (s, &ep, 0, loc);
-  CHECK_RES (s, ret_ll, ep, expected_ll);
+  CHECK_RES (s, ret_ll, ep, expected_ll, expected_p);
   ret_ll = FNX (ll_l) (s, &ep, 2, loc);
-  CHECK_RES (s, ret_ll, ep, expected_ll);
+  CHECK_RES (s, ret_ll, ep, expected_ll, expected_p);
   ret_ull = FNX (ull_l) (s, &ep, 0, loc);
-  CHECK_RES (s, ret_ull, ep, expected_ull);
+  CHECK_RES (s, ret_ull, ep, expected_ull, expected_p);
   ret_ull = FNX (ull_l) (s, &ep, 2, loc);
-  CHECK_RES (s, ret_ull, ep, expected_ull);
+  CHECK_RES (s, ret_ull, ep, expected_ull, expected_p);
 #endif
 }
 
 static int
 do_test (void)
 {
-  one_check (L_("0b101"), 5, 5, 5, 5);
-  one_check (L_("0B101"), 5, 5, 5, 5);
-  one_check (L_("-0b11111"), -31, -31, -31, -31);
-  one_check (L_("-0B11111"), -31, -31, -31, -31);
-  one_check (L_("0b111111111111111111111111111111111"),
+  {
+    const CHAR *input = L_("0b");
+    one_check (input, input + 1, 0L, 0UL, 0LL, 0ULL);
+  }
+  one_check (L_("0b101"), NULL, 5, 5, 5, 5);
+  one_check (L_("0B101"), NULL, 5, 5, 5, 5);
+  one_check (L_("-0b11111"), NULL, -31, -31, -31, -31);
+  one_check (L_("-0B11111"), NULL, -31, -31, -31, -31);
+  one_check (L_("0b111111111111111111111111111111111"), NULL,
             LONG_MAX >= 0x1ffffffffLL ? (long int) 0x1ffffffffLL : LONG_MAX,
             (ULONG_MAX >= 0x1ffffffffULL
              ? (unsigned long int) 0x1ffffffffULL
              : ULONG_MAX),
             0x1ffffffffLL, 0x1ffffffffULL);
-  one_check (L_("0B111111111111111111111111111111111"),
+  one_check (L_("0B111111111111111111111111111111111"), NULL,
             LONG_MAX >= 0x1ffffffffLL ? (long int) 0x1ffffffffLL : LONG_MAX,
             (ULONG_MAX >= 0x1ffffffffULL
              ? (unsigned long int) 0x1ffffffffULL
              : ULONG_MAX),
             0x1ffffffffLL, 0x1ffffffffULL);
-  one_check (L_("-0b111111111111111111111111111111111"),
+  one_check (L_("-0b111111111111111111111111111111111"), NULL,
             LONG_MIN <= -0x1ffffffffLL ? (long int) -0x1ffffffffLL : LONG_MIN,
             (ULONG_MAX >= 0x1ffffffffULL
              ? (unsigned long int) -0x1ffffffffULL
              : ULONG_MAX),
             -0x1ffffffffLL, -0x1ffffffffULL);
-  one_check (L_("-0B111111111111111111111111111111111"),
+  one_check (L_("-0B111111111111111111111111111111111"), NULL,
             LONG_MIN <= -0x1ffffffffLL ? (long int) -0x1ffffffffLL : LONG_MIN,
             (ULONG_MAX >= 0x1ffffffffULL
              ? (unsigned long int) -0x1ffffffffULL
index bff1d879f07a8b2f0ebcb980c47f86ced881628d..fdd79ec9e09b23e84689eff9ad77899caf66f6b0 100644 (file)
@@ -20,6 +20,7 @@
 #undef _GNU_SOURCE
 
 #define CHAR wchar_t
+#define WIDE 1
 #define FNPFX wcsto
 #define L_(C) L ## C
 #define TEST_C2X 0
index 0f8ef44854107f82570cac91a9d3c537b56177ce..6c06dab9ba655733d5e9473557fb599e376ef464 100644 (file)
@@ -23,6 +23,7 @@
 #define _ISOC2X_SOURCE
 
 #define CHAR wchar_t
+#define WIDE 1
 #define FNPFX wcsto
 #define L_(C) L ## C
 #define TEST_C2X 1
index 189f2175637f18d229ddf24a2191524449c07177..1a3d5d3d6c7052811bc9563f3c9d19bb1f3d2eeb 100644 (file)
@@ -25,6 +25,7 @@
 #define __GLIBC_USE_C2X_STRTOL 0
 
 #define CHAR wchar_t
+#define WIDE 1
 #define FNPFX wcsto
 #define L_(C) L ## C
 #define TEST_C2X 0
index 707d4076f162277453f64d8bf52c492796f6a47f..feda1b59dd1326836e8f35e1e3b518d800a43c28 100644 (file)
@@ -18,6 +18,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #define CHAR wchar_t
+#define WIDE 1
 #define FNPFX wcsto
 #define L_(C) L ## C
 #define TEST_C2X 1