diff options
author | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2023-05-25 08:14:37 -0300 |
---|---|---|
committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2023-05-25 09:28:23 -0300 |
commit | 95c9a6e806226cbf174c92efc021a0d464f170a4 (patch) | |
tree | 0a02ebbc928a183e2328c265494b1915f5b658b8 | |
parent | e0189b25403f8b67e7a5513d6c33fb09cb2e5e20 (diff) | |
download | glibc-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>
-rw-r--r-- | stdlib/strtol_l.c | 10 | ||||
-rw-r--r-- | stdlib/tst-strtol-binary-c11.c | 1 | ||||
-rw-r--r-- | stdlib/tst-strtol-binary-c2x.c | 1 | ||||
-rw-r--r-- | stdlib/tst-strtol-binary-gnu11.c | 1 | ||||
-rw-r--r-- | stdlib/tst-strtol-binary-gnu2x.c | 1 | ||||
-rw-r--r-- | stdlib/tst-strtol-binary-main.c | 86 | ||||
-rw-r--r-- | wcsmbs/tst-wcstol-binary-c11.c | 1 | ||||
-rw-r--r-- | wcsmbs/tst-wcstol-binary-c2x.c | 1 | ||||
-rw-r--r-- | wcsmbs/tst-wcstol-binary-gnu11.c | 1 | ||||
-rw-r--r-- | wcsmbs/tst-wcstol-binary-gnu2x.c | 1 |
10 files changed, 65 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 diff --git a/wcsmbs/tst-wcstol-binary-c11.c b/wcsmbs/tst-wcstol-binary-c11.c index bff1d87..fdd79ec 100644 --- a/wcsmbs/tst-wcstol-binary-c11.c +++ b/wcsmbs/tst-wcstol-binary-c11.c @@ -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 diff --git a/wcsmbs/tst-wcstol-binary-c2x.c b/wcsmbs/tst-wcstol-binary-c2x.c index 0f8ef44..6c06dab 100644 --- a/wcsmbs/tst-wcstol-binary-c2x.c +++ b/wcsmbs/tst-wcstol-binary-c2x.c @@ -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 diff --git a/wcsmbs/tst-wcstol-binary-gnu11.c b/wcsmbs/tst-wcstol-binary-gnu11.c index 189f217..1a3d5d3 100644 --- a/wcsmbs/tst-wcstol-binary-gnu11.c +++ b/wcsmbs/tst-wcstol-binary-gnu11.c @@ -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 diff --git a/wcsmbs/tst-wcstol-binary-gnu2x.c b/wcsmbs/tst-wcstol-binary-gnu2x.c index 707d407..feda1b5 100644 --- a/wcsmbs/tst-wcstol-binary-gnu2x.c +++ b/wcsmbs/tst-wcstol-binary-gnu2x.c @@ -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 |