From patchwork Mon Jun 26 16:43:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 113049 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp7614503vqr; Mon, 26 Jun 2023 09:47:12 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ74yVhJmlsJQTxcJfbpKhcB3eQzzr8gJ/tFWjm8m2JWzTxj77vWtBgJZRhM4aq4OIOAwB3r X-Received: by 2002:a05:6402:b0a:b0:51d:9339:1cd0 with SMTP id bm10-20020a0564020b0a00b0051d93391cd0mr3820326edb.20.1687798032733; Mon, 26 Jun 2023 09:47:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1687798032; cv=none; d=google.com; s=arc-20160816; b=xXKV1dPBh7Ltg+zPWSTCSbcdKI/OPzFUUZVcQRb6N8NOmSHE9+wsPo5DTZvFzL7DWW tVIpp9EW6FPlb+26KoFc8108MXrfXPLToCQxpAkI6iM932ng8g9vW58jGpngQCYEGFYr h1LWqQwJDJzoSy17u4jTgA4Y+c1AVFOaMJdfFtujeM/3yD2KrSXCQ3VBpKe1Ju7doxaI fPTrNhhpKOIUP3va6qGzzQxy9fL1kGoV8KCwhdAKGdenL0v5Fbt+Qg2mP2FUC2FqAYWL tLA0KB5pLYLNXxF7fEqHrjoZNkcZF7D56ZiCuvhzOrk9l30rLrp9JKgF03moiTvV8eOQ rOZg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-transfer-encoding:mime-version:message-id:date:subject:to :dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=SNyKPDqmFfeecRSxefsoi5fIz/tEikmxxzkjdcQ0gAU=; fh=sJ+2/4g29YdyXkoRrFZSpsL2zxijepB7X/1rB0LDDh8=; b=xGEdIdsJlkpaBngR0G0QGkICfoQ3AmQ3GmIvbYWPNWVawfqTAiUgZQw+hxdeSA6jac NFfWl7MDRu2IgdobhEw+InoYd7UwIgvWMz9dMPQrBktsMmpMGbDiNcE7s4PM3eEnhpzG vu2RsdaP2Ez23I2xMH++EqigiDIwkmoTK25TPoSYePxYR6A6mHmrCuRoKIObqMtQkG7Y OC1bkj3m38pUJNMVH4XInnsYP4tcr+RVosIWUesqJHxA476fHhAu4NRj2rXDovYwyOI1 3b/koEIQSOdxMY5BojEQvOXfGB/QIvLzDPMe5gRt4OIFsfm1oQ9vp8a8J+IcF8r65DgH oFtw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=Y8umXOG9; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id u12-20020a50eacc000000b0051a39840146si2842780edp.464.2023.06.26.09.47.12 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 26 Jun 2023 09:47:12 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=Y8umXOG9; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A6CB638313A7 for ; Mon, 26 Jun 2023 16:45:25 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A6CB638313A7 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1687797925; bh=SNyKPDqmFfeecRSxefsoi5fIz/tEikmxxzkjdcQ0gAU=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=Y8umXOG9WX3KYJZvT0yfE6OZdHlqYtkbjB/SI+Ik4qO+ne0g5ujf4dy3EihME9owW VjCUSlJEPMPxFTbtavzM+IZTPTa/f+f7yXYWA5JNplEIeTmtl/7flQmy0Vd3YK2dtZ FbiKi6isC7CbuP/jK57Wdn/UmPFhoJTvfzTdmUxU= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id D8D9B3857727 for ; Mon, 26 Jun 2023 16:44:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D8D9B3857727 Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-517-4Wv5ld5jPfaFb-mPUuD6Zg-1; Mon, 26 Jun 2023 12:44:17 -0400 X-MC-Unique: 4Wv5ld5jPfaFb-mPUuD6Zg-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id AE1863C13949; Mon, 26 Jun 2023 16:44:05 +0000 (UTC) Received: from localhost (unknown [10.42.28.110]) by smtp.corp.redhat.com (Postfix) with ESMTP id 79222200B677; Mon, 26 Jun 2023 16:44:05 +0000 (UTC) To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Fix std::format for pointers [PR110239] Date: Mon, 26 Jun 2023 17:43:51 +0100 Message-ID: <20230626164404.270512-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jonathan Wakely via Gcc-patches From: Jonathan Wakely Reply-To: Jonathan Wakely Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1769784510069578514?= X-GMAIL-MSGID: =?utf-8?q?1769784510069578514?= Tested x86_64-linux. Pushed to trunk. -- >8 -- The formatter for pointers was casting to uint64_t which sign extends a 32-bit pointer and produces a value that won't fit in the provided buffer. Cast to uintptr_t instead. There was also a bug in the __parse_integer helper when converting a wide string to a narrow string in order to use std::from_chars on it. The function would always try to read 32 characters, even if the format string was shorter than that. Fix that bug, and remove the constexpr implementation of __parse_integer by just using __from_chars_alnum instead of from_chars, because that's usable in constexpr even in C++20. libstdc++-v3/ChangeLog: PR libstdc++/110239 * include/std/format (__format::__parse_integer): Fix buffer overflow for wide chars. (formatter::format): Cast to uintptr_t instead of uint64_t. * testsuite/std/format/string.cc: Test too-large widths. --- libstdc++-v3/include/std/format | 33 +++++++-------------- libstdc++-v3/testsuite/std/format/string.cc | 5 ++++ 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index 96a1e62ccc8..9d5981e4882 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -269,39 +269,26 @@ namespace __format if (__first == __last) __builtin_unreachable(); - // TODO: use this loop unconditionally? - // Most integers used for arg-id, width or precision will be small. - if (is_constant_evaluated()) - { - auto __next = __first; - unsigned short __val = 0; - while (__next != __last && '0' <= *__next && *__next <= '9') - { - __val = (__val * 10) + (*__next - '0'); // TODO check overflow? - ++__next; - } - if (__next == __first) - return {0, nullptr}; - return {__val, __next}; - } - - unsigned short __val = 0; if constexpr (is_same_v<_CharT, char>) { - auto [ptr, ec] = std::from_chars(__first, __last, __val); - if (ec == errc{}) - return {__val, ptr}; - return {0, nullptr}; + const auto __start = __first; + unsigned short __val = 0; + // N.B. std::from_chars is not constexpr in C++20. + if (__detail::__from_chars_alnum(__first, __last, __val, 10) + && __first != __start) [[likely]] + return {__val, __first}; } else { + unsigned short __val = 0; constexpr int __n = 32; char __buf[__n]{}; - for (int __i = 0; __i < __n && __first != __last; ++__i) + for (int __i = 0; __i < __n && (__first + __i) != __last; ++__i) __buf[__i] = __first[__i]; auto [__v, __ptr] = __format::__parse_integer(__buf, __buf + __n); return {__v, __first + (__ptr - __buf)}; } + return {0, nullptr}; } template @@ -2118,7 +2105,7 @@ namespace __format typename basic_format_context<_Out, _CharT>::iterator format(const void* __v, basic_format_context<_Out, _CharT>& __fc) const { - auto __u = reinterpret_cast<__UINT64_TYPE__>(__v); + auto __u = reinterpret_cast<__UINTPTR_TYPE__>(__v); char __buf[2 + sizeof(__v) * 2]; auto [__ptr, __ec] = std::to_chars(__buf + 2, std::end(__buf), __u, 16); diff --git a/libstdc++-v3/testsuite/std/format/string.cc b/libstdc++-v3/testsuite/std/format/string.cc index e421028a873..d28135ec260 100644 --- a/libstdc++-v3/testsuite/std/format/string.cc +++ b/libstdc++-v3/testsuite/std/format/string.cc @@ -121,6 +121,11 @@ test_format_spec() // Invalid presentation types for strings. VERIFY( ! is_format_string_for("{:S}", "str") ); VERIFY( ! is_format_string_for("{:d}", "str") ); + + // Maximum integer value supported for widths and precisions is USHRT_MAX. + VERIFY( is_format_string_for("{:65535}", 1) ); + VERIFY( ! is_format_string_for("{:65536}", 1) ); + VERIFY( ! is_format_string_for("{:9999999}", 1) ); } int main()