Hi,
Stefan wrote:
> I'm facing troubles with your change to gnulib regarding strtod. In
> particular there is a problem with this code in lib/strtod.c:
> ...
>
> This problem shows up when using musl built with tinycc. In this particular
> case the NAN macro of musl is defined as (0.0f/0.0f) and at least on x86_64
> this is -NaN and not +NaN.
Yes, I've seen such an effect on some platforms too. Otherwise,
gnulib/lib/signed-nan.h would be simpler than it is.
> If musl is compiled with gcc, then its NAN macro is defined as the
> __builtin_nanf("") of gcc, which is +NaN.
On some platforms, __builtin_nanf("") in gcc is wrong too.
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111814>.
> The C standard does not specify the sign of the NAN macro, it is
> implementation-defined¹.
Yes, but at least one GNU package that uses Gnulib needs the sign working
right in strtof() and strtod(). That's why Gnulib attempts to get it right,
even though it's beyond ISO C.
> This general -NaN result of strtod is not expected by gnulib and not handled
> properly and therefore test-strtod and test-c-strtod fail.
Good to hear that the test suite is sufficiently beefed up in this area.
> I see two issues with the code above. First of all, it only tries to set the
> sign bit if the string has the minus sign. It does not check if the result is
> -NaN in case the string is missing the minus sign.
Indeed. Thanks for the report! Fixed through the patch below.
> The second problem is with "value = - value;". This is not guaranteed to
> change the sign of any ±NaN value. The C standard seems to only offer two
> functions to work with the sign of NaN values portably³⁴, which are signbit
> and copysign.
In practice, this works on all architectures I've seen. No need to change
the code for it. In fact gnulib's lib/copysign.c uses the unary minus operator
too.
Bruno
2026-11-05 Bruno Haible <[email protected]>
strtof, strtod, strtold: Fix sign of NaN results.
Reported by Stefan <[email protected]> in
<https://lists.gnu.org/archive/html/bug-gnulib/2026-11/msg00037.html>.
* lib/strtod.c (STRTOD) [HAS_MINUS_NAN_BUG]: Also apply a sign
correction if the input does not have a '-' sign and the underlying
STRTOD function returned a negative NaN.
diff --git a/lib/strtod.c b/lib/strtod.c
index 3bdf2c5e9a..9604aa063d 100644
--- a/lib/strtod.c
+++ b/lib/strtod.c
@@ -157,7 +157,7 @@ STRTOD (const char *nptr, char **endptr)
{
while (locale_isspace (*nptr))
nptr++;
- if (*nptr == '-' && !signbit (value))
+ if ((*nptr == '-') != !!signbit (value))
value = - value;
}
return value;