bin/102424: printf(3) prints ill result.

Tsurutani Naoki turutani at
Wed Aug 23 08:50:25 UTC 2006

>Number:         102424
>Category:       bin
>Synopsis:       printf(3) prints ill result.
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Aug 23 08:50:18 GMT 2006
>Originator:     Tsurutani Naoki
>Release:        FreeBSD 6.1-STABLE amd64
System: FreeBSD 6.1-STABLE FreeBSD 6.1-STABLE #3: Fri Aug 11 12:02:50 JST 2006 turutani at amd64

	output via printf(3) is wrong on some special case.
	on FreeBSD/amd64 and compile for 32bit by gcc (or copied i386 binary),
	next code prints irregal output:
		#include <stdio.h>
		int main()
			union {
				double a;
				int i[2];
			} b;
			b.i[1] = 0x3fb99999;
			b.i[0] = 0x99999999;
			fprintf(stdout, "%f, %.8x %.8x\n", b.a, b.i[1], b.i[0]);
			return 0;
	expected output is:
		0.100000, 3fb99999 99999999
	but on above mensioned environment,
		0.0:0000, 3fb99999 99999999
	0x3fb9999999999999 is a little fewer value than 0.1 in decimal.
	this happens only on amd64, and do not happen with 64bit binary
	and on i386 machine.
	"10" is ('0'+1)//('0'+0), and "0:" is ('0'+0)//('0'+10)...
	character of each digit and its position are inconsequent.
	everytime when compile with following way:
	% gcc -m32 -L/usr/lib32 -B/usr/lib32 foo.c -o foo
	/etc/make.conf has no CFLAGS.
	After compile all the 32bit libraries with "CFLAGS= -O" instead of "-O2"
	and install them, no trouble with above code occurs.
	And compile with "-O2" and install them makes trouble again.
	As man page of make.conf(5) and /usr/share/mk/ say,
	"-O2" in CFLAGS is now a supported feature, so this is a bug.
	This trouble happend with direct using of __dtoa() defined in
	src/contrib/gdtoa/dtoa.c, with the same compile options, or use it
	in libc.
	Therefore this is thought to be a bug in __dtoa() or compiler.
	Note that this does not occurs under "-O" libraries even if compile
	directly with dtoa.c and -O2 options.
	the following is another code:
		#include <stdio.h>
		#include <stdlib.h>
		#define dtoa __dtoa
		char* __dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve);
		int main()
			union {
				double d;
				int b[2];
			} a;
			int decpt, sign;
			char *ptr, *ret;
			a.b[1] = 0x3fb99999;
			a.b[0] = 0x99999999;
			ret = __dtoa(a.d, 3, 6, &decpt, &sign, &ptr);
			printf("decpt = %d\n", decpt);
			printf("returned string is \"%s\"\n", ret);
			return 0;

	this prints
		decpt = 0
		returned string is "1"
	on normal case, and
		decpt = 1
		returned string is ":"
	on wrong case.


More information about the freebsd-bugs mailing list