+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
/* 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
#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
#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
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
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)