about summary refs log tree commit diff
path: root/stdlib/tst-strtol-binary-main.c
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2023-05-25 08:14:37 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2023-05-25 09:28:23 -0300
commit95c9a6e806226cbf174c92efc021a0d464f170a4 (patch)
tree0a02ebbc928a183e2328c265494b1915f5b658b8 /stdlib/tst-strtol-binary-main.c
parente0189b25403f8b67e7a5513d6c33fb09cb2e5e20 (diff)
downloadglibc-95c9a6e806226cbf174c92efc021a0d464f170a4.tar.gz
glibc-95c9a6e806226cbf174c92efc021a0d464f170a4.tar.xz
glibc-95c9a6e806226cbf174c92efc021a0d464f170a4.zip
Fix special case for C2x strtol binary constant handling (BZ# 30371)
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>
Diffstat (limited to 'stdlib/tst-strtol-binary-main.c')
-rw-r--r--stdlib/tst-strtol-binary-main.c86
1 files changed, 50 insertions, 36 deletions
diff --git a/stdlib/tst-strtol-binary-main.c b/stdlib/tst-strtol-binary-main.c
index ece3100298..54cda5cd03 100644
--- a/stdlib/tst-strtol-binary-main.c
+++ b/stdlib/tst-strtol-binary-main.c
@@ -21,6 +21,7 @@
 #include <locale.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <wchar.h>
 
 #include <support/check.h>
@@ -32,13 +33,19 @@
 #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								\
 	{								\
@@ -51,95 +58,102 @@
   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