public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-7699] libstdc++: Fix incorrect use of abs and log10 in std::format [PR110860]
@ 2023-08-08 16:13 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2023-08-08 16:13 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:a059403794add2934961780662e320ba77798a7e

commit r13-7699-ga059403794add2934961780662e320ba77798a7e
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.
    
    (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

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-08-08 16:13 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-08 16:13 [gcc r13-7699] libstdc++: Fix incorrect use of abs and log10 in std::format [PR110860] Jonathan Wakely

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).