Bug 17914

Summary: float-to-double core dump on 3.4R
Product: Base System Reporter: Randall Hopper <aa8vb>
Component: i386Assignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me CC: aa8vb
Priority: Normal    
Version: 3.4-RELEASE   
Hardware: Any   
OS: Any   

Description Randall Hopper 2000-04-11 01:50:00 UTC
	     #include <float.h>
	
	     main()
	     {
	        float  f = FLT_MAX;
	        double d;
	        f = f * 2;
	        d = f;
	     }
	
	Delete the "d=f" line and it doesn't core.  Put it in and it does
	(floating-point exception).
	
	From this it appears there may be a bug in the float-to-double
	promotion when f is Inf (or, at least I'd expect that f is Inf).

	Note that the core dump does not occur when the Inf is generated,
        but only when it is promoted to a double.

        I first noticed this by trying to printf the value of f after f=f*2
	and got the same core-dump behavior (due to float-to-double arg
	promotion).

Fix: 

Unknown.
How-To-Repeat: 
	Paste the above snippet into a .c file, compile with cc -o tst
	tst.c, and execute.
Comment 1 toasty 2000-04-11 04:47:51 UTC
> 	     #include <float.h>
> 	
> 	     main()
> 	     {
> 	        float  f = FLT_MAX;
> 	        double d;
> 	        f = f * 2;
> 	        d = f;
> 	     }
> 	
> 	Delete the "d=f" line and it doesn't core.  Put it in and it does
> 	(floating-point exception).
> 	
> 	From this it appears there may be a bug in the float-to-double
> 	promotion when f is Inf (or, at least I'd expect that f is Inf).
> 
> 	Note that the core dump does not occur when the Inf is generated,
>         but only when it is promoted to a double.
> 
>         I first noticed this by trying to printf the value of f after f=f*2
> 	and got the same core-dump behavior (due to float-to-double arg
> 	promotion).


See 'man setfpmask'. The default behavior in 3.4 was to cause a SIGFPE if
you do anything that causes an 'overflow' to be generated from the FPU. I
admit this is weird that it's doing it here, but I don't claim to understand
what happens in a case like this. :)

(4.0 and higher changed their defaults to ignore certain exceptions)


Kevin
Comment 2 Bruce Evans 2000-04-11 05:39:21 UTC
On Mon, 10 Apr 2000 aa8vb@ipass.net wrote:

> >Description:
> 
> 	     #include <float.h>
> 	
> 	     main()
> 	     {
> 	        float  f = FLT_MAX;
> 	        double d;
> 	        f = f * 2;
> 	        d = f;
> 	     }
> 	
> 	Delete the "d=f" line and it doesn't core.  Put it in and it does
> 	(floating-point exception).
> 	
> 	From this it appears there may be a bug in the float-to-double
> 	promotion when f is Inf (or, at least I'd expect that f is Inf).

No.  "f * 2" gives undefined behaviour since it overflows.  For FreeBSD-3.4
on i386's, the actual behaviour is to leave the operands on the FP stack
and cause a SIGFPE on the next FP instruction after the one that overflowed.

> 	Note that the core dump does not occur when the Inf is generated,
>         but only when it is promoted to a double.

Inf is not generated.  The operands are left on the FP stack for the SIGFPE
handler to fix up.  This behaviour is easy to see using gdb ("display/i $pc",
"stepi" and "info float").

Bruce
Comment 3 Sheldon Hearn freebsd_committer freebsd_triage 2000-04-11 14:04:16 UTC
State Changed
From-To: open->closed

Asked and answered. 

Comment 4 Randall Hopper 2000-04-12 00:06:52 UTC
Bruce Evans:
 |> 	        float  f = FLT_MAX;
 |> 	        double d;
 |> 	        f = f * 2;
 |> 	        d = f;
 |> 	
 |> 	Delete the "d=f" line and it doesn't core.  Put it in and it does
 |> 	(floating-point exception).
 |> 	
 |> 	From this it appears there may be a bug in the float-to-double
 |> 	promotion when f is Inf (or, at least I'd expect that f is Inf).
 |
 |No.  "f * 2" gives undefined behaviour since it overflows.  For FreeBSD-3.4
 |on i386's, the actual behaviour is to leave the operands on the FP stack
 |and cause a SIGFPE on the next FP instruction after the one that overflowed.
 |
 |> 	Note that the core dump does not occur when the Inf is generated,
 |>         but only when it is promoted to a double.
 |
 |Inf is not generated.  The operands are left on the FP stack for the SIGFPE
 |handler to fix up.  This behaviour is easy to see using gdb ("display/i $pc",
 |"stepi" and "info float").

Ok, thanks for your clarification.  That seems like very odd behavior to
wait until the "next" floating point instruction before signaling the
exception for the prior.  That could potentially be pages away in the
instruction stream.

Intuitively it seems like a bug (like waiting for a while before tripping a
divide by zero fault).  But I'll trust that you know more about the issues
involved here than I do.

Thanks for the reply,

Randall
Comment 5 Randall Hopper 2000-04-12 00:42:02 UTC
Randall Hopper:
 |Ok, thanks for your clarification.  That seems like very odd behavior to
 |wait until the "next" floating point instruction before signaling the
 |exception for the prior.  That could potentially be pages away in the
 |instruction stream.

Thomas David Rivers:
 |>  Intuitively it seems like a bug (like waiting for a while before
 |>  tripping a divide by zero fault).  But I'll trust that you know more
 |>  about the issues involved here than I do.
 |
 | It's how the fpu works in the x86 chip; an artifact of when the
 | FPU was a different chip.
 |
 | Some x86 compilers can be told to emit an extra instruction (kinda
 | like a dummy floating pt. instruction) so that any except can be
 | caught synchronously; but when you do this, it *really* slows down
 | floating point operations.

Ok, thank you.  That makes sense.  I understand the behavior now.

Randall.