]> Savannah Git Hosting - gnulib.git/commitdiff
vasnprintf: Don't abort for pseudo-denormal arguments on macOS 12.
authorBruno Haible <bruno@clisp.org>
Mon, 20 May 2024 22:33:55 +0000 (00:33 +0200)
committerBruno Haible <bruno@clisp.org>
Wed, 22 May 2024 09:06:05 +0000 (11:06 +0200)
Reported by Gaëtan Herfray <g.herfray@gahfy.io> via Erik Blake in
<https://lists.gnu.org/archive/html/bug-m4/2022-03/msg00002.html>
<https://lists.gnu.org/archive/html/bug-gnulib/2022-03/msg00066.html>.

* lib/vasnprintf.c (safe_frexpl): New function.
(decode_long_double, floorlog10l): Invoke it instead of frexpl.

ChangeLog
lib/vasnprintf.c

index d28c01b3801c39afd2f58bec4c47f30b21a66f88..0a060a444b6bdfcb0edf45e0be7f0685baab4cf7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2024-05-20  Bruno Haible  <bruno@clisp.org>
+
+       vasnprintf: Don't abort for pseudo-denormal arguments on macOS 12.
+       Reported by Gaëtan Herfray <g.herfray@gahfy.io> via Erik Blake in
+       <https://lists.gnu.org/archive/html/bug-m4/2022-03/msg00002.html>
+       <https://lists.gnu.org/archive/html/bug-gnulib/2022-03/msg00066.html>.
+       * lib/vasnprintf.c (safe_frexpl): New function.
+       (decode_long_double, floorlog10l): Invoke it instead of frexpl.
+
 2024-05-20  Paul Eggert  <eggert@cs.ucla.edu>
 
        getopt-posix: port better to Alpine 3.20.0_rc1
index 8d20ffb358b79c97dffb3bb00671e795de925a19..cc1f271e0fbea29b60aecfd3112c1b113876af22 100644 (file)
@@ -1,5 +1,5 @@
 /* vsprintf with automatic memory allocation.
-   Copyright (C) 1999, 2002-2023 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2002-2024 Free Software Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as
@@ -86,7 +86,7 @@
 #include <wchar.h>      /* mbstate_t, mbrtowc(), mbrlen(), wcrtomb() */
 #include <errno.h>      /* errno */
 #include <limits.h>     /* CHAR_BIT, INT_WIDTH, LONG_WIDTH */
-#include <float.h>      /* DBL_MAX_EXP, LDBL_MAX_EXP */
+#include <float.h>      /* DBL_MAX_EXP, LDBL_MAX_EXP, LDBL_MANT_DIG */
 #if HAVE_NL_LANGINFO
 # include <langinfo.h>
 #endif
@@ -406,6 +406,40 @@ is_infinite_or_zerol (long double x)
 
 #endif
 
+#if NEED_PRINTF_LONG_DOUBLE
+
+/* Like frexpl, except that it supports even "unsupported" numbers.  */
+# if (LDBL_MANT_DIG == 64 && (defined __ia64 || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))) && (defined __APPLE__ && defined __MACH__)
+/* Don't assume that frexpl can handle pseudo-denormals; it does not on
+   macOS 12/x86_64.  Therefore test for a pseudo-denormal explicitly.  */
+
+static
+long double safe_frexpl (long double x, int *exp)
+{
+  union
+    {
+      long double value;
+      struct { unsigned int mant_word[2]; unsigned short sign_exp_word; } r;
+    }
+  u;
+  u.value = x;
+  if (u.r.sign_exp_word == 0 && (u.r.mant_word[1] & 0x80000000u) != 0)
+    {
+      /* Pseudo-Denormal.  */
+      *exp = LDBL_MIN_EXP;
+      u.r.sign_exp_word = 1 - LDBL_MIN_EXP;
+      return u.value;
+    }
+  else
+    return frexpl (x, exp);
+}
+
+# else
+#  define safe_frexpl frexpl
+# endif
+
+#endif
+
 #if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE
 
 /* Converting 'long double' to decimal without rare rounding bugs requires
@@ -1015,7 +1049,7 @@ decode_long_double (long double x, int *ep, mpn_t *mp)
   if (m.limbs == NULL)
     return NULL;
   /* Split into exponential part and mantissa.  */
-  y = frexpl (x, &exp);
+  y = safe_frexpl (x, &exp);
   if (!(y >= 0.0L && y < 1.0L))
     abort ();
   /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * 2^LDBL_MANT_BIT), and the
@@ -1442,7 +1476,7 @@ floorlog10l (long double x)
   double l;
 
   /* Split into exponential part and mantissa.  */
-  y = frexpl (x, &exp);
+  y = safe_frexpl (x, &exp);
   if (!(y >= 0.0L && y < 1.0L))
     abort ();
   if (y == 0.0L)