[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Linking libc causes wrong results when casting double to long long



>Submitter-Id:  net
>Originator:    Marcus Holland-Moritz
>Organization:
net
>Synopsis:      Linking libc causes wrong results when casting double to long long
>Severity:      serious
>Priority:      high
>Category:      system
>Class:         sw-bug
>Release:       3.4
>Environment:
        <machine, os, target, libraries (multiple lines)>
        System      : OpenBSD 3.4
        Architecture: OpenBSD.i386
        Machine     : i386
>Description:
        When casting a double larger than 2**32 to an unsigned long long,
	this gives correct results when _not_ linking libc, but _wrong_
	results when linking libc.
>How-To-Repeat:
        You can easily reproduce with the following snippet of C code
	run under OpenBSD 3.3 and 3.4 (3.5 is identical to 3.4):

	$ uname -a                        
	OpenBSD openbsd33.mhxnet 3.3 GENERIC#44 i386
	$ cat test.c                           
	#include <stdio.h>
	
	typedef double NV;
	typedef unsigned long long UV;
	
	int main(void)
	{
	  NV f = 4294967303.15;
	  UV u = (UV) f;
	  printf("%f => %llu\n", f, u);
	  return 0;
	}
	$ cc -o test test.c && ./test     
	4294967303.150000 => 4294967303
	$ cc -o test -lc test.c && ./test 
	4294967303.150000 => 4294967303
	                     ^^^^^^^^^^  CORRECT

	$ uname -a
	OpenBSD openbsd34.mhxnet 3.4 GENERIC#18 i386
	$ cat test.c                      
	#include <stdio.h>
	
	typedef double NV;
	typedef unsigned long long UV;
	
	int main(void)
	{
	  NV f = 4294967303.15;
	  UV u = (UV) f;
	  printf("%f => %llu\n", f, u);
	  return 0;
	}
	$ cc -o test test.c && ./test     
	4294967303.150000 => 4294967303
	$ cc -o test -lc test.c && ./test 
	4294967303.150000 => 4294967304
	                     ^^^^^^^^^^  WRONG

>Fix:
	Not sure what the root cause is, but the problem seems to have to do
	with gcc's and libc's different implementations of __fixunsdfdi().