Bug 659 - strtold() returns meaningless number on Asus WL-500gP router w/OpenWRT
Summary: strtold() returns meaningless number on Asus WL-500gP router w/OpenWRT
Status: RESOLVED WORKSFORME
Alias: None
Product: uClibc
Classification: Unclassified
Component: Standard Compliance (show other bugs)
Version: <= 0.9.29.x
Hardware: Other Linux
: P5 normal
Target Milestone: ---
Assignee: unassigned
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-10-14 13:12 UTC by Charles Kerr
Modified: 2010-03-17 11:33 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
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.