From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2181) id 5F692385772C; Tue, 8 Aug 2023 16:13:29 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 5F692385772C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1691511209; bh=WUucAF6Bkc0A87WSTagfYXHRCyKZdjC6qNE7QgFbamg=; h=From:To:Subject:Date:From; b=RA/cCWiEyqo/VYjZj9kQk5p8mF7PZeJjZcYrFTFJtvA7FsgP2c7ibFJgivKiGuQYM ywqzvCuRnHdBn7JIqOASWkCsMX9Bvlrp/V0DwvjRUFoaSgCkNGFOqCfIfXEdyEBV9z MCV7A9Qtx3V+ZEPYxYl56jMNqK1+U3CjMSzm0NEE= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jonathan Wakely To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r13-7699] libstdc++: Fix incorrect use of abs and log10 in std::format [PR110860] X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/heads/releases/gcc-13 X-Git-Oldrev: 0f0152a93d15b24ebc7f6c7455baaded6a63fb2e X-Git-Newrev: a059403794add2934961780662e320ba77798a7e Message-Id: <20230808161329.5F692385772C@sourceware.org> Date: Tue, 8 Aug 2023 16:13:29 +0000 (GMT) List-Id: https://gcc.gnu.org/g:a059403794add2934961780662e320ba77798a7e commit r13-7699-ga059403794add2934961780662e320ba77798a7e Author: Jonathan Wakely Date: Mon Aug 7 15:30:03 2023 +0100 libstdc++: Fix incorrect use of abs and log10 in std::format [PR110860] 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. (cherry picked from commit bb3ceeb6520c13fc5ca08af7d43fbd3f975e72b0) Diff: --- 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 e624b9fe353..96bf17e2aa1 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -1485,9 +1485,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