bug-m4
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Make check - test-vasprintf-posix failure - darwin12 - macos


From: Bruno Haible
Subject: Re: Make check - test-vasprintf-posix failure - darwin12 - macos
Date: Tue, 21 May 2024 03:46:53 +0200

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

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)






reply via email to

[Prev in Thread] Current Thread [Next in Thread]