From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 274083856956 for ; Mon, 7 Aug 2023 21:14:31 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 274083856956 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691442870; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=EvoX+cssMVQcaSumR2VtGnYc5B3hqkVW2/E/c7DAQps=; b=gkYxiRH/aH3/Ovwuz2SQ3QZGHOwBv3nGC66Sxw1FRX8aE7u+H9Mh1h+ds5NShOvpyPB9GQ ScrOv8ujCuRbUVNNx8tVlBo8UmLWldPGbWcbEebFGGtetJAtpqgsejIO6IYd2Iaer0b54x mYYUe4YCcaYvoR3AU8lZGkIY8B/xFm0= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-480-n4jxUWrWMs6daeP1iTzGdg-1; Mon, 07 Aug 2023 17:14:29 -0400 X-MC-Unique: n4jxUWrWMs6daeP1iTzGdg-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 029988DC671; Mon, 7 Aug 2023 21:14:29 +0000 (UTC) Received: from localhost (unknown [10.42.28.127]) by smtp.corp.redhat.com (Postfix) with ESMTP id BC4762026D4B; Mon, 7 Aug 2023 21:14:28 +0000 (UTC) From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Fix incorrect use of abs and log10 in std::format [PR110860] Date: Mon, 7 Aug 2023 22:14:22 +0100 Message-ID: <20230807211428.701867-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 Content-Type: text/plain Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-11.8 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_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Tested x86_64-linux. Pushed to trunk. gcc-13 backport to follow. -- >8 -- The std::formatter implementation for floating-point types uses __builtin_abs and __builtin_log10 to avoid including all of , but those functions are not generic. The result of abs(2e304) is -INT_MIN which is undefined, and then log10(INT_MIN) is NaN. As well as being undefined, we fail to grow the buffer correctly, and then loop more times than needed to allocate a buffer and try formatting the value into it again. We can use if-constexpr to choose the correct form of log10 to use for the type, and avoid using abs entirely. This avoids the undefined behaviour and should mean we only reallocate and retry std::to_chars once. libstdc++-v3/ChangeLog: PR libstdc++/110860 * include/std/format (__formatter_fp::format): Do not use __builtin_abs and __builtin_log10 with arbitrary floating-point types. --- libstdc++-v3/include/std/format | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index 60e53642b11..f68308e7210 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -1487,9 +1487,20 @@ namespace __format { // If the buffer is too small it's probably because of a large // precision, or a very large value in fixed format. - size_t __guess = __prec + sizeof(__buf); - if (__fmt == chars_format::fixed) - __guess += max((int)__builtin_log10(__builtin_abs(__v)) / 2, 1); + size_t __guess = 8 + __prec; + if (__fmt == chars_format::fixed) // +ddd.prec + { + if constexpr (is_same_v<_Fp, float>) + __guess += __builtin_log10f(__v < 0.0f ? -__v : __v); + else if constexpr (is_same_v<_Fp, double>) + __guess += __builtin_log10(__v < 0.0 ? -__v : __v); + else if constexpr (is_same_v<_Fp, long double>) + __guess += __builtin_log10l(__v < 0.0l ? -__v : __v); + else + __guess += numeric_limits<_Fp>::max_exponent10; + } + if (__guess <= sizeof(__buf)) [[unlikely]] + __guess = sizeof(__buf) * 2; __dynbuf.reserve(__guess); do -- 2.41.0