Bug 659

Summary: strtold() returns meaningless number on Asus WL-500gP router w/OpenWRT
Product: uClibc Reporter: Charles Kerr <charles>
Component: Standard ComplianceAssignee: unassigned
Status: RESOLVED WORKSFORME    
Severity: normal CC: uclibc-cvs
Priority: P5    
Version: <= 0.9.29.x   
Target Milestone: ---   
Hardware: Other   
OS: Linux   
Host: Target:
Build:

Description Charles Kerr 2009-10-14 13:12:46 UTC
This was reported by a Transmission user running uclibc 0.9.29 on OpenWRT 8.09.1 (on a Asus WL-500gP).  The upstream ticket is at http://trac.transmissionbt.com/ticket/2360.

This code block:

   fprintf( stderr, "%s:%d json parser parsing float [%s]\n", __FILE__, __LINE__ (char*)jc->parse_buffer ); 
   /* value.vu.float_value is of type "long double" */
   value.vu.float_value = strtold(jc->parse_buffer, NULL); 
   fprintf( stderr, "%s:%d strtold gives [%.f]\n", __FILE__, __LINE__ (double)value.vu.float_value ); 

Yields this:

   JSON_parser.c:492 json parser parsing float [2.0000]
   JSON_parser.c:501 strtold gives [721567744]

Changing value.vu.float_value's type from "long double" to "double", and strtold() to strtod(), reportedly works.

At a guess, it's possibly a width issue?  I don't know how wide that Asus router thinks "long double" is...
Comment 1 Bernhard Reutner-Fischer 2010-03-12 18:43:32 UTC
This sounds more like a miscompilation to me, but i don't know what hardware that router is.

I'm closing this for now since it works for me (see below). Don't hesitate to reopen if you can provide more detail.

thanks,

$ gcc -Os strtold.c && ./a.out
Lg=2
g =2
f =2.000000
$ cat strtold.c 
#include <stdlib.h>
#include <stdio.h>
int main(void) {
	printf("Lg=%Lg\n", strtold("2.0000", NULL));
	printf("g =%g\n", strtod("2.0000", NULL));
	printf("f =%f\n", strtof("2.0000", NULL));
	return 0;
}
Comment 2 Leonid 2010-03-14 18:13:59 UTC
I also can confirm erroneous strtold() output on MIPS32 LE platform. Your sample produces output like:

$ ./strtold
Lg=2.122e-314
g =2
f =0.000000

toolchain used: gcc is 4.2.4, uClibc 0.9.30.1, binutils 2.19.1

If I changes example like:

#include <stdlib.h>
#include <stdio.h>

int main(void) {
        long double ld = 0;
        float f = 0;

        ld = strtold("2.0000", NULL);
        f = strtof("2.0000", NULL);

        printf("Lg=%Lg\n", ld);
        printf("g =%g\n", strtod("2.0000", NULL));
        printf("f =%f\n", f);

        return 0;
}

output will be:

$ ./strtold
Lg=7.16427e+08
g =2
f =716427264.000000
Comment 3 Leonid 2010-03-14 19:03:24 UTC
Sorry, this is a kind of miscompilation bug - according to strtold manual, it REQUIRES even for glibc:

==========================================================================
  Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

    strtof(),  strtold():  _XOPEN_SOURCE >= 600   ||   _ISOC99_SOURCE;   or
    cc -std=c99
==========================================================================
I simply forgot to provide -std=c99 when compiling test-case, so please close the bug.