This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug stdio/22752] New: strtold/printf errors for "long double" on ppc64


https://sourceware.org/bugzilla/show_bug.cgi?id=22752

            Bug ID: 22752
           Summary: strtold/printf errors for "long double" on ppc64
           Product: glibc
           Version: 2.26
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: stdio
          Assignee: unassigned at sourceware dot org
          Reporter: allan.haldane at gmail dot com
  Target Milestone: ---

I've noticed two possible bugs related to reading/writing "long double" types
on ppc64, where it has the "IBM double double" 128-bit binary format.

First, it is possible to construct two values whose printf output is identical,
but which are not equal. This has to do with treatment of the 107th bit, which
was also discussed here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70117

It is not clear to me whether glibc is right to ignore the 107th bit and treat
them equal, and that gcc should also ignore the 107th bit, or not.

---------------- Example 1 -------------
#include <stdio.h>
#include <stdint.h>

union unpack{
    struct { uint64_t a, b; } ip;
    long double d;
};

int main(){
    /* equiv to strtold("2")/strtold("3") */
    union unpack x = {4604180019048437077ull, 4360985639170430293ull};
    /* equiv to strtold("0.66666666666666666666666666666666") */
    union unpack y = {4604180019048437077ull, 4360985639170430292ull};

    printf("%.40Lg\n", x.d);
    printf(x.d == y.d ? "==\n" : "!=\n");
    printf("%.40Lg\n", y.d);
}
------ Output (glibc 2.26, gcc 7.3.0) -------
0.6666666666666666666666666666666584493656
!=
0.6666666666666666666666666666666584493656
---------------------------------------------



Second, strtold fails for any long-double which is subnormal or near-subnormal.
The following example shows it is possible to create the value '5e-294' by
division, but strtold fails to read it because the lower double is subnormal.
It actually writes the correct value but still sets errno, so the fix might be
as simple as not setting errno.

---------------- Example 2 -------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main(){
    long double x;
    char str[1024], *end;

    x = strtold("5.0e-292", &end)/100;
    printf("%.40Lg\n", x);

    /* reconstruct x from its string representation */
    snprintf(str, 1024, "%.40Lg", x);
    x = 0;  /* reset to 0 to see if it gets overwritten */
    errno = 0;
    x = strtold(str, &end);
    if (errno != 0) {
        printf("error: %s\n", strerror(errno));
    }
    printf("%.40Lg\n", x);
}
------ Output (glibc 2.26, gcc 7.3.0) -------
5.000000000000000000000000000002042787298e-294
error: Numerical result out of range
5.000000000000000000000000000002042787298e-294
---------------------------------------------

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]