aboutsummaryrefslogtreecommitdiff
path: root/stdlib
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
parente0189b25403f8b67e7a5513d6c33fb09cb2e5e20 (diff)
downloadglibc-95c9a6e806226cbf174c92efc021a0d464f170a4.zip
glibc-95c9a6e806226cbf174c92efc021a0d464f170a4.tar.gz
glibc-95c9a6e806226cbf174c92efc021a0d464f170a4.tar.bz2
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')
-rw-r--r--stdlib/strtol_l.c10
-rw-r--r--stdlib/tst-strtol-binary-c11.c1
-rw-r--r--stdlib/tst-strtol-binary-c2x.c1
-rw-r--r--stdlib/tst-strtol-binary-gnu11.c1
-rw-r--r--stdlib/tst-strtol-binary-gnu2x.c1
-rw-r--r--stdlib/tst-strtol-binary-main.c86
6 files changed, 61 insertions, 39 deletions
diff --git a/stdlib/strtol_l.c b/stdlib/strtol_l.c
index 3424c3f..548b46a 100644
--- a/stdlib/strtol_l.c
+++ b/stdlib/strtol_l.c
@@ -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
diff --git a/stdlib/tst-strtol-binary-c11.c b/stdlib/tst-strtol-binary-c11.c
index 6e58bb2..8b8c31c 100644
--- a/stdlib/tst-strtol-binary-c11.c
+++ b/stdlib/tst-strtol-binary-c11.c
@@ -20,6 +20,7 @@
#undef _GNU_SOURCE
#define CHAR char
+#define WIDE 0
#define FNPFX strto
#define L_(C) C
#define TEST_C2X 0
diff --git a/stdlib/tst-strtol-binary-c2x.c b/stdlib/tst-strtol-binary-c2x.c
index b9ccfda..e75f088 100644
--- a/stdlib/tst-strtol-binary-c2x.c
+++ b/stdlib/tst-strtol-binary-c2x.c
@@ -23,6 +23,7 @@
#define _ISOC2X_SOURCE
#define CHAR char
+#define WIDE 0
#define FNPFX strto
#define L_(C) C
#define TEST_C2X 1
diff --git a/stdlib/tst-strtol-binary-gnu11.c b/stdlib/tst-strtol-binary-gnu11.c
index a029591..7dc8131 100644
--- a/stdlib/tst-strtol-binary-gnu11.c
+++ b/stdlib/tst-strtol-binary-gnu11.c
@@ -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
diff --git a/stdlib/tst-strtol-binary-gnu2x.c b/stdlib/tst-strtol-binary-gnu2x.c
index 0a7fdd4..96db241 100644
--- a/stdlib/tst-strtol-binary-gnu2x.c
+++ b/stdlib/tst-strtol-binary-gnu2x.c
@@ -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
diff --git a/stdlib/tst-strtol-binary-main.c b/stdlib/tst-strtol-binary-main.c
index ece3100..54cda5c 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