public inbox for libstdc++-cvs@sourceware.org help / color / mirror / Atom feed
From: Jonathan Wakely <redi@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r14-3069] libstdc++: Fix incorrect use of abs and log10 in std::format [PR110860] Date: Mon, 7 Aug 2023 21:14:06 +0000 (GMT) [thread overview] Message-ID: <20230807211406.9B2CD3858032@sourceware.org> (raw) https://gcc.gnu.org/g:bb3ceeb6520c13fc5ca08af7d43fbd3f975e72b0 commit r14-3069-gbb3ceeb6520c13fc5ca08af7d43fbd3f975e72b0 Author: Jonathan Wakely <jwakely@redhat.com> 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 <cmath>, 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. 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 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
reply other threads:[~2023-08-07 21:14 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20230807211406.9B2CD3858032@sourceware.org \ --to=redi@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ --cc=libstdc++-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).