From patchwork Thu May 25 11:20:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 70068 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D233F3858CDB for ; Thu, 25 May 2023 11:21:02 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D233F3858CDB DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1685013662; bh=KxbKcNOzlPe0RIiCfxSaPlEK46Zhc2+8eR5L2iO6iyo=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=GuxEcZXFig5iwvCBzqc9diCPETFkSPE9VtI9fle6sAgDV6WeS/PNt9npvhJnuYrWi ds43kSAt3itsV9vp6uOT9C5Pbwj0ssFYNb8YYCDONAkMFWyNbKkzDujUo8AV+erW/x ImMctIF8XiIkEWnk9H90+KZbNW4ruSGYHcftIQws= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-oo1-xc30.google.com (mail-oo1-xc30.google.com [IPv6:2607:f8b0:4864:20::c30]) by sourceware.org (Postfix) with ESMTPS id 7DEC03858D32 for ; Thu, 25 May 2023 11:20:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7DEC03858D32 Received: by mail-oo1-xc30.google.com with SMTP id 006d021491bc7-5552cbcda35so197775eaf.1 for ; Thu, 25 May 2023 04:20:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685013638; x=1687605638; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=KxbKcNOzlPe0RIiCfxSaPlEK46Zhc2+8eR5L2iO6iyo=; b=N7/d9eUCJDwPitqe5rqyhWTe0FB6EZK4y5YZFNgTVJvhqwfR3yjDBHtYB0J8eO5JBQ SDW3taevdKrg4DdEcv4K1WdEVr53CPe4JoeN0vL1YPTN5nHRHQlkHfS6ZvZPZNbRt/K+ cpRt3ZU4e4CUarOU0Gky48AfNEwJKWreZCtNzvXfzDTM+mEhO8zXZy17Dxtn4+vxsAqO ewXBGLeaYXriBiAN+40dbNBBhciDh8mV5u79TPgCOU4XQ83uNAtXUwPHT7yskHkm2S8e Hb4fXH4abz1bs+eW2SFqVOBjBV9k7cXGiBDIxV0B8wAKjQFvuo/PJqzDOudbk++jCoCc SqpQ== X-Gm-Message-State: AC+VfDw7Gcv2pLrxm1EV9HJDTNYp7agmp6dCninjGLWNALHQj1ylpNLo /SbTpkV29vy7ojC/O252MTS3TcLdi8dodEuRt+vA/A== X-Google-Smtp-Source: ACHHUZ7Vn8viuPT02w3V+/FUxE/OvUe9iHw9wr4wxeFFaUyRREutyxi4MO/JoM2EAi1zKIXwOE99qQ== X-Received: by 2002:a4a:6c1a:0:b0:555:5348:f2b with SMTP id q26-20020a4a6c1a000000b0055553480f2bmr4887538ooc.0.1685013638045; Thu, 25 May 2023 04:20:38 -0700 (PDT) Received: from mandiga.. ([2804:1b3:a7c1:4dd5:1f:68d0:3218:bdf0]) by smtp.gmail.com with ESMTPSA id o201-20020a4a2cd2000000b005526983ebdcsm358418ooo.4.2023.05.25.04.20.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 May 2023 04:20:37 -0700 (PDT) To: libc-alpha@sourceware.org, Bruno Haible Subject: [PATCH] Fix special case for C2x strtol binary constant handling (BZ# 30371) Date: Thu, 25 May 2023 08:20:32 -0300 Message-Id: <20230525112032.4041628-1-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 X-Spam-Status: No, score=-12.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" 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 --- stdlib/strtol_l.c | 10 ++-- stdlib/tst-strtol-binary-c11.c | 1 + stdlib/tst-strtol-binary-c2x.c | 1 + stdlib/tst-strtol-binary-gnu11.c | 1 + stdlib/tst-strtol-binary-gnu2x.c | 1 + stdlib/tst-strtol-binary-main.c | 86 +++++++++++++++++++------------- wcsmbs/tst-wcstol-binary-c11.c | 1 + wcsmbs/tst-wcstol-binary-c2x.c | 1 + wcsmbs/tst-wcstol-binary-gnu11.c | 1 + 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 3424c3feab..548b46aa52 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 6e58bb2599..8b8c31cdd0 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 b9ccfda759..e75f0881b6 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 a029591c8b..7dc81317df 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 0a7fdd4d4d..96db2414b9 100644 --- a/stdlib/tst-strtol-binary-gnu2x.c +++ b/stdlib/tst-strtol-binary-gnu2x.c @@ -18,6 +18,7 @@ . */ #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 ece3100298..54cda5cd03 100644 --- a/stdlib/tst-strtol-binary-main.c +++ b/stdlib/tst-strtol-binary-main.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -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 bff1d879f0..fdd79ec9e0 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 0f8ef44854..6c06dab9ba 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 189f217563..1a3d5d3d6c 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 707d4076f1..feda1b59dd 100644 --- a/wcsmbs/tst-wcstol-binary-gnu2x.c +++ b/wcsmbs/tst-wcstol-binary-gnu2x.c @@ -18,6 +18,7 @@ . */ #define CHAR wchar_t +#define WIDE 1 #define FNPFX wcsto #define L_(C) L ## C #define TEST_C2X 1