Gaëtan HERFRAY wrote and Eric Blake forwarded in <https://lists.gnu.org/archive/html/bug-gnulib/2022-03/msg00066.html>:
> > Actually, make check is failing on test-vasprintf-posix. > > Thanks for the report. This test is maintained by gnulib, so other > projects may see the same failure in that test. Or it may have been > fixed in the meantime (I still need to release an updated version of > m4). > > > After investigating, I found that they are 3 tests that are failing, about > > pseudo denormal (you can find the four tests by looking for "{ LDBL80_WORDS > > (0x0000, 0x83333333, 0x00000000) }". > > > > Only the first one pass, the three next are failing. > > > > First question: are those tests important? > > They are important to gnulib, as it helps find places where we still > need to work around platform bugs. But they are less important to m4, > which does not output floating point numbers, and therefore does not > need to worry about printf() bugs in dealing with pseudo-denormal bit > values. Sorry for the long delay. I can reproduce the issue with CI tests on some macOS 12 machine. There, I get this unit test output: FAIL: test-vasnprintf-posix =========================== Stack trace: 0x105a3f33f print_stack_trace ../../gllib/abort-debug.c:40 0x105a3f33f rpl_abort ../../gllib/abort-debug.c:94 0x105a46f30 floorlog10l ../../gllib/vasnprintf.c:1450 0x105a41e70 vasnprintf ../../gllib/vasnprintf.c:4571 0x105a3f271 my_asnprintf ../../gltests/test-vasnprintf-posix.c:5252 0x105a28318 test_function ../../gltests/test-vasnprintf-posix.c:1568 0x105a1f2ff test_vasnprintf ../../gltests/test-vasnprintf-posix.c:5260 0x105a1f2ff main ../../gltests/test-vasnprintf-posix.c:5272 FAIL test-vasnprintf-posix (exit status: 134) It seems that the macOS 12 'frexpl' function does not handle the pseudo-denormal values appropriately. The patch below fixes the test failures. Note: While investigating the *printf results on pseudo-denormal values, I found that glibc does not do it consistently: <https://sourceware.org/bugzilla/show_bug.cgi?id=31769>. 2024-05-20 Bruno Haible <br...@clisp.org> vasnprintf: Don't abort for pseudo-denormal arguments on macOS 12. Reported by Gaëtan Herfray <g.herf...@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. diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index 6f06273081..ac8dc8619e 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -86,7 +86,7 @@ #include <wchar.h> /* mbstate_t, mbrtowc(), mbrlen(), wcrtomb(), mbszero() */ #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 /* An indicator for a failed memory allocation. */ @@ -1018,7 +1052,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 @@ -1445,7 +1479,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)