mailing list of musl libc
 help / color / mirror / code / Atom feed
* [musl] strtod doesn't set errno to ERANGE for slightly out-of-range hex float
@ 2025-03-24 10:55 Lénárd Szolnoki
  2025-04-08 22:25 ` Szabolcs Nagy
  0 siblings, 1 reply; 5+ messages in thread
From: Lénárd Szolnoki @ 2025-03-24 10:55 UTC (permalink / raw)
  To: musl

Hi,

#include <stdlib.h>
#include <assert.h>
#include <errno.h>

int main() {
   const char* const input = "0x1.fffffffffffff8p+1023";
   double ret = strtod(input, NULL);
   assert(errno == ERANGE);
}

The input is slightly out of range, DBL_MAX is 1.fffffffffffffp+1023 (one fewer binary 1 
in the mantissa).

The assert fails with musl libc, passes with glibc.

musl version: 1.2.5 (as shipped in Debian sid)

Regards,
Lénárd Szolnoki

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [musl] strtod doesn't set errno to ERANGE for slightly out-of-range hex float
  2025-03-24 10:55 [musl] strtod doesn't set errno to ERANGE for slightly out-of-range hex float Lénárd Szolnoki
@ 2025-04-08 22:25 ` Szabolcs Nagy
  2025-04-09 10:38   ` Lénárd Szolnoki
  0 siblings, 1 reply; 5+ messages in thread
From: Szabolcs Nagy @ 2025-04-08 22:25 UTC (permalink / raw)
  To: Lénárd Szolnoki; +Cc: musl

* Lénárd Szolnoki <cpp@lenardszolnoki.com> [2025-03-24 10:55:36 +0000]:
> Hi,
> 
> #include <stdlib.h>
> #include <assert.h>
> #include <errno.h>
> 
> int main() {
>   const char* const input = "0x1.fffffffffffff8p+1023";
>   double ret = strtod(input, NULL);
>   assert(errno == ERANGE);
> }
> 
> The input is slightly out of range, DBL_MAX is 1.fffffffffffffp+1023 (one
> fewer binary 1 in the mantissa).
> 
> The assert fails with musl libc, passes with glibc.

this looks valid (might depend on long double
representation).

the overflow threshold is not calculated precisely
for the hexfloat case. __floatscan returns an in
range long double value that is rounded to inf by
strtod, but there is no overflow check there.

i guess hexfloat overflow check should be fixed.

> 
> musl version: 1.2.5 (as shipped in Debian sid)
> 
> Regards,
> Lénárd Szolnoki

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [musl] strtod doesn't set errno to ERANGE for slightly out-of-range hex float
  2025-04-08 22:25 ` Szabolcs Nagy
@ 2025-04-09 10:38   ` Lénárd Szolnoki
  2025-04-09 12:55     ` Szabolcs Nagy
  0 siblings, 1 reply; 5+ messages in thread
From: Lénárd Szolnoki @ 2025-04-09 10:38 UTC (permalink / raw)
  To: musl; +Cc: nsz



On 08/04/2025 23:25, Szabolcs Nagy wrote:
> * Lénárd Szolnoki <cpp@lenardszolnoki.com> [2025-03-24 10:55:36 +0000]:
>> Hi,
>>
>> #include <stdlib.h>
>> #include <assert.h>
>> #include <errno.h>
>>
>> int main() {
>>    const char* const input = "0x1.fffffffffffff8p+1023";
>>    double ret = strtod(input, NULL);
>>    assert(errno == ERANGE);
>> }
>>
>> The input is slightly out of range, DBL_MAX is 1.fffffffffffffp+1023 (one
>> fewer binary 1 in the mantissa).
>>
>> The assert fails with musl libc, passes with glibc.
> 
> this looks valid (might depend on long double
> representation).

Good point, maybe I should have used strtof. Anyway, I am testing on x86_64 Linux, with 
80bit long double.

> 
> the overflow threshold is not calculated precisely
> for the hexfloat case. __floatscan returns an in
> range long double value that is rounded to inf by
> strtod, but there is no overflow check there.

An other test case is with a different behaviour is 
"0x1.fffffffffffff00000000000000000000000000000000000000000000001p+1023"

This is even more slightly larger than DBL_MAX, therefore it should still return inf and 
set errno to ERANGE.

For this one strtod returns DBL_MAX. What happens is that this rounds towards the value of 
DBL_MAX within long double, and the conversion from long double to double is exact, so it 
does not overflow. Sort of a double rounding problem, but at the edge of the range of double.

> 
> i guess hexfloat overflow check should be fixed.
> 
>>
>> musl version: 1.2.5 (as shipped in Debian sid)
>>
>> Regards,
>> Lénárd Szolnoki


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [musl] strtod doesn't set errno to ERANGE for slightly out-of-range hex float
  2025-04-09 10:38   ` Lénárd Szolnoki
@ 2025-04-09 12:55     ` Szabolcs Nagy
  2025-04-09 13:20       ` Lénárd Szolnoki
  0 siblings, 1 reply; 5+ messages in thread
From: Szabolcs Nagy @ 2025-04-09 12:55 UTC (permalink / raw)
  To: Lénárd Szolnoki; +Cc: musl

* Lénárd Szolnoki <cpp@lenardszolnoki.com> [2025-04-09 11:38:01 +0100]:
> On 08/04/2025 23:25, Szabolcs Nagy wrote:
> > * Lénárd Szolnoki <cpp@lenardszolnoki.com> [2025-03-24 10:55:36 +0000]:
> > > Hi,
> > > 
> > > #include <stdlib.h>
> > > #include <assert.h>
> > > #include <errno.h>
> > > 
> > > int main() {
> > >    const char* const input = "0x1.fffffffffffff8p+1023";
> > >    double ret = strtod(input, NULL);
> > >    assert(errno == ERANGE);
> > > }
> > > 
> > > The input is slightly out of range, DBL_MAX is 1.fffffffffffffp+1023 (one
> > > fewer binary 1 in the mantissa).
> > > 
> > > The assert fails with musl libc, passes with glibc.
...
> > the overflow threshold is not calculated precisely
> > for the hexfloat case. __floatscan returns an in
> > range long double value that is rounded to inf by
> > strtod, but there is no overflow check there.
> 
> An other test case is with a different behaviour is
> "0x1.fffffffffffff00000000000000000000000000000000000000000000001p+1023"
> 
> This is even more slightly larger than DBL_MAX, therefore it should still
> return inf and set errno to ERANGE.
> 

in nearest rounding mode i'd expect DBL_MAX.

in upward rounding mode musl seems to return inf.

> For this one strtod returns DBL_MAX. What happens is that this rounds
> towards the value of DBL_MAX within long double, and the conversion from
> long double to double is exact, so it does not overflow. Sort of a double
> rounding problem, but at the edge of the range of double.

there is only a single rounding, and i think that's fine.


> > 
> > i guess hexfloat overflow check should be fixed.
> > 
> > > 
> > > musl version: 1.2.5 (as shipped in Debian sid)
> > > 
> > > Regards,
> > > Lénárd Szolnoki

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [musl] strtod doesn't set errno to ERANGE for slightly out-of-range hex float
  2025-04-09 12:55     ` Szabolcs Nagy
@ 2025-04-09 13:20       ` Lénárd Szolnoki
  0 siblings, 0 replies; 5+ messages in thread
From: Lénárd Szolnoki @ 2025-04-09 13:20 UTC (permalink / raw)
  To: musl; +Cc: Szabolcs Nagy



On 09/04/2025 13:55, Szabolcs Nagy wrote:
> * Lénárd Szolnoki <cpp@lenardszolnoki.com> [2025-04-09 11:38:01 +0100]:
>> On 08/04/2025 23:25, Szabolcs Nagy wrote:
>>> * Lénárd Szolnoki <cpp@lenardszolnoki.com> [2025-03-24 10:55:36 +0000]:
>>>> Hi,
>>>>
>>>> #include <stdlib.h>
>>>> #include <assert.h>
>>>> #include <errno.h>
>>>>
>>>> int main() {
>>>>     const char* const input = "0x1.fffffffffffff8p+1023";
>>>>     double ret = strtod(input, NULL);
>>>>     assert(errno == ERANGE);
>>>> }
>>>>
>>>> The input is slightly out of range, DBL_MAX is 1.fffffffffffffp+1023 (one
>>>> fewer binary 1 in the mantissa).
>>>>
>>>> The assert fails with musl libc, passes with glibc.
> ...
>>> the overflow threshold is not calculated precisely
>>> for the hexfloat case. __floatscan returns an in
>>> range long double value that is rounded to inf by
>>> strtod, but there is no overflow check there.
>>
>> An other test case is with a different behaviour is
>> "0x1.fffffffffffff00000000000000000000000000000000000000000000001p+1023"
>>
>> This is even more slightly larger than DBL_MAX, therefore it should still
>> return inf and set errno to ERANGE.
>>
> 
> in nearest rounding mode i'd expect DBL_MAX.

It appears that you are right. I expected DBL_MAX to be the threshold for all rounding 
modes, but I double checked the IEEE standard and it seems that for nearest rounding mode 
the threshold is exactly my first example.

> 
> in upward rounding mode musl seems to return inf.
> 
>> For this one strtod returns DBL_MAX. What happens is that this rounds
>> towards the value of DBL_MAX within long double, and the conversion from
>> long double to double is exact, so it does not overflow. Sort of a double
>> rounding problem, but at the edge of the range of double.
> 
> there is only a single rounding, and i think that's fine.
> 
> 
>>>
>>> i guess hexfloat overflow check should be fixed.
>>>
>>>>
>>>> musl version: 1.2.5 (as shipped in Debian sid)
>>>>
>>>> Regards,
>>>> Lénárd Szolnoki


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2025-04-09 13:20 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-03-24 10:55 [musl] strtod doesn't set errno to ERANGE for slightly out-of-range hex float Lénárd Szolnoki
2025-04-08 22:25 ` Szabolcs Nagy
2025-04-09 10:38   ` Lénárd Szolnoki
2025-04-09 12:55     ` Szabolcs Nagy
2025-04-09 13:20       ` Lénárd Szolnoki

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).