mirror of
git://sourceware.org/git/glibc.git
synced 2025-01-30 12:31:53 +08:00
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>
This commit is contained in:
parent
e0189b2540
commit
95c9a6e806
@ -526,11 +526,15 @@ INTERNAL (__strtol_l) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
|
|||||||
noconv:
|
noconv:
|
||||||
/* We must handle a special case here: the base is 0 or 16 and the
|
/* 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
|
first two characters are '0' and 'x', but the rest are no
|
||||||
hexadecimal digits. This is no error case. We return 0 and
|
hexadecimal digits. Likewise when the base is 0 or 2 and the
|
||||||
ENDPTR points to the `x`. */
|
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 (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'))
|
&& save[-2] == L_('0'))
|
||||||
*endptr = (STRING_TYPE *) &save[-1];
|
*endptr = (STRING_TYPE *) &save[-1];
|
||||||
else
|
else
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#undef _GNU_SOURCE
|
#undef _GNU_SOURCE
|
||||||
|
|
||||||
#define CHAR char
|
#define CHAR char
|
||||||
|
#define WIDE 0
|
||||||
#define FNPFX strto
|
#define FNPFX strto
|
||||||
#define L_(C) C
|
#define L_(C) C
|
||||||
#define TEST_C2X 0
|
#define TEST_C2X 0
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#define _ISOC2X_SOURCE
|
#define _ISOC2X_SOURCE
|
||||||
|
|
||||||
#define CHAR char
|
#define CHAR char
|
||||||
|
#define WIDE 0
|
||||||
#define FNPFX strto
|
#define FNPFX strto
|
||||||
#define L_(C) C
|
#define L_(C) C
|
||||||
#define TEST_C2X 1
|
#define TEST_C2X 1
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#define __GLIBC_USE_C2X_STRTOL 0
|
#define __GLIBC_USE_C2X_STRTOL 0
|
||||||
|
|
||||||
#define CHAR char
|
#define CHAR char
|
||||||
|
#define WIDE 0
|
||||||
#define FNPFX strto
|
#define FNPFX strto
|
||||||
#define L_(C) C
|
#define L_(C) C
|
||||||
#define TEST_C2X 0
|
#define TEST_C2X 0
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
<https://www.gnu.org/licenses/>. */
|
<https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
#define CHAR char
|
#define CHAR char
|
||||||
|
#define WIDE 0
|
||||||
#define FNPFX strto
|
#define FNPFX strto
|
||||||
#define L_(C) C
|
#define L_(C) C
|
||||||
#define TEST_C2X 1
|
#define TEST_C2X 1
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
|
||||||
#include <support/check.h>
|
#include <support/check.h>
|
||||||
@ -32,13 +33,19 @@
|
|||||||
#define CONCAT(X, Y) CONCAT_ (X, Y)
|
#define CONCAT(X, Y) CONCAT_ (X, Y)
|
||||||
#define FNX(FN) CONCAT (FNPFX, FN)
|
#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 \
|
do \
|
||||||
{ \
|
{ \
|
||||||
if (TEST_C2X) \
|
if (TEST_C2X) \
|
||||||
{ \
|
{ \
|
||||||
TEST_COMPARE ((RES), EXPECTED); \
|
TEST_COMPARE ((RES), EXPECTED); \
|
||||||
TEST_COMPARE (*(EP), 0); \
|
TEST_VERIFY ((EP) == EXPECTED_EP); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
{ \
|
{ \
|
||||||
@ -51,95 +58,102 @@
|
|||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
one_check (const CHAR *s, long int expected_l, unsigned long int expected_ul,
|
one_check (const CHAR *s, const CHAR *expected_p, long int expected_l,
|
||||||
long long int expected_ll, unsigned long long int expected_ull)
|
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;
|
CHAR *ep;
|
||||||
long int ret_l;
|
long int ret_l;
|
||||||
unsigned long int ret_ul;
|
unsigned long int ret_ul;
|
||||||
long long int ret_ll;
|
long long int ret_ll;
|
||||||
unsigned long long int ret_ull;
|
unsigned long long int ret_ull;
|
||||||
ret_l = FNX (l) (s, &ep, 0);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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
|
#if TEST_Q
|
||||||
ret_ll = FNX (q) (s, &ep, 0);
|
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);
|
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);
|
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);
|
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
|
#endif
|
||||||
#if TEST_LOCALE
|
#if TEST_LOCALE
|
||||||
locale_t loc = xnewlocale (LC_NUMERIC_MASK, "C", (locale_t) 0);
|
locale_t loc = xnewlocale (LC_NUMERIC_MASK, "C", (locale_t) 0);
|
||||||
ret_l = FNX (l_l) (s, &ep, 0, loc);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
do_test (void)
|
do_test (void)
|
||||||
{
|
{
|
||||||
one_check (L_("0b101"), 5, 5, 5, 5);
|
{
|
||||||
one_check (L_("0B101"), 5, 5, 5, 5);
|
const CHAR *input = L_("0b");
|
||||||
one_check (L_("-0b11111"), -31, -31, -31, -31);
|
one_check (input, input + 1, 0L, 0UL, 0LL, 0ULL);
|
||||||
one_check (L_("-0B11111"), -31, -31, -31, -31);
|
}
|
||||||
one_check (L_("0b111111111111111111111111111111111"),
|
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,
|
LONG_MAX >= 0x1ffffffffLL ? (long int) 0x1ffffffffLL : LONG_MAX,
|
||||||
(ULONG_MAX >= 0x1ffffffffULL
|
(ULONG_MAX >= 0x1ffffffffULL
|
||||||
? (unsigned long int) 0x1ffffffffULL
|
? (unsigned long int) 0x1ffffffffULL
|
||||||
: ULONG_MAX),
|
: ULONG_MAX),
|
||||||
0x1ffffffffLL, 0x1ffffffffULL);
|
0x1ffffffffLL, 0x1ffffffffULL);
|
||||||
one_check (L_("0B111111111111111111111111111111111"),
|
one_check (L_("0B111111111111111111111111111111111"), NULL,
|
||||||
LONG_MAX >= 0x1ffffffffLL ? (long int) 0x1ffffffffLL : LONG_MAX,
|
LONG_MAX >= 0x1ffffffffLL ? (long int) 0x1ffffffffLL : LONG_MAX,
|
||||||
(ULONG_MAX >= 0x1ffffffffULL
|
(ULONG_MAX >= 0x1ffffffffULL
|
||||||
? (unsigned long int) 0x1ffffffffULL
|
? (unsigned long int) 0x1ffffffffULL
|
||||||
: ULONG_MAX),
|
: ULONG_MAX),
|
||||||
0x1ffffffffLL, 0x1ffffffffULL);
|
0x1ffffffffLL, 0x1ffffffffULL);
|
||||||
one_check (L_("-0b111111111111111111111111111111111"),
|
one_check (L_("-0b111111111111111111111111111111111"), NULL,
|
||||||
LONG_MIN <= -0x1ffffffffLL ? (long int) -0x1ffffffffLL : LONG_MIN,
|
LONG_MIN <= -0x1ffffffffLL ? (long int) -0x1ffffffffLL : LONG_MIN,
|
||||||
(ULONG_MAX >= 0x1ffffffffULL
|
(ULONG_MAX >= 0x1ffffffffULL
|
||||||
? (unsigned long int) -0x1ffffffffULL
|
? (unsigned long int) -0x1ffffffffULL
|
||||||
: ULONG_MAX),
|
: ULONG_MAX),
|
||||||
-0x1ffffffffLL, -0x1ffffffffULL);
|
-0x1ffffffffLL, -0x1ffffffffULL);
|
||||||
one_check (L_("-0B111111111111111111111111111111111"),
|
one_check (L_("-0B111111111111111111111111111111111"), NULL,
|
||||||
LONG_MIN <= -0x1ffffffffLL ? (long int) -0x1ffffffffLL : LONG_MIN,
|
LONG_MIN <= -0x1ffffffffLL ? (long int) -0x1ffffffffLL : LONG_MIN,
|
||||||
(ULONG_MAX >= 0x1ffffffffULL
|
(ULONG_MAX >= 0x1ffffffffULL
|
||||||
? (unsigned long int) -0x1ffffffffULL
|
? (unsigned long int) -0x1ffffffffULL
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#undef _GNU_SOURCE
|
#undef _GNU_SOURCE
|
||||||
|
|
||||||
#define CHAR wchar_t
|
#define CHAR wchar_t
|
||||||
|
#define WIDE 1
|
||||||
#define FNPFX wcsto
|
#define FNPFX wcsto
|
||||||
#define L_(C) L ## C
|
#define L_(C) L ## C
|
||||||
#define TEST_C2X 0
|
#define TEST_C2X 0
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#define _ISOC2X_SOURCE
|
#define _ISOC2X_SOURCE
|
||||||
|
|
||||||
#define CHAR wchar_t
|
#define CHAR wchar_t
|
||||||
|
#define WIDE 1
|
||||||
#define FNPFX wcsto
|
#define FNPFX wcsto
|
||||||
#define L_(C) L ## C
|
#define L_(C) L ## C
|
||||||
#define TEST_C2X 1
|
#define TEST_C2X 1
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#define __GLIBC_USE_C2X_STRTOL 0
|
#define __GLIBC_USE_C2X_STRTOL 0
|
||||||
|
|
||||||
#define CHAR wchar_t
|
#define CHAR wchar_t
|
||||||
|
#define WIDE 1
|
||||||
#define FNPFX wcsto
|
#define FNPFX wcsto
|
||||||
#define L_(C) L ## C
|
#define L_(C) L ## C
|
||||||
#define TEST_C2X 0
|
#define TEST_C2X 0
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
<https://www.gnu.org/licenses/>. */
|
<https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
#define CHAR wchar_t
|
#define CHAR wchar_t
|
||||||
|
#define WIDE 1
|
||||||
#define FNPFX wcsto
|
#define FNPFX wcsto
|
||||||
#define L_(C) L ## C
|
#define L_(C) L ## C
|
||||||
#define TEST_C2X 1
|
#define TEST_C2X 1
|
||||||
|
Loading…
Reference in New Issue
Block a user