Bug 7298

Summary: FP divide by zero exception when printing double 0.0
Product: uClibc Reporter: Zia <drivingon9>
Component: OtherAssignee: unassigned
Status: RESOLVED DUPLICATE    
Severity: major CC: uclibc-cvs
Priority: P5    
Version: unspecified   
Target Milestone: ---   
Hardware: Other   
OS: Linux   
Host: Target:
Build:

Description Zia 2014-08-07 17:23:12 UTC
The file _fpmaxtpstr.c contains code that looks like this:
============================================================
… 
#define zeroisnegative(x)    ((1./(x)) < 0) 
… 

ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, 
                                                                          __fp_outfunc_t fp_outfunc) 
…. 
               if (x == 0) {                                                      /* Handle 0 now to avoid false positive. */ 
#ifdef __UCLIBC_HAVE_SIGNED_ZERO__ 
                              if (zeroisnegative(x)) { /* Handle 'signed' zero. */ 
                                            *sign_str = '-'; 
                              } 
#endif /* __UCLIBC_HAVE_SIGNED_ZERO__ */ 
                              exp = -1; 
                              goto GENERATE_DIGITS; 
               } 
============================================================

The "zeroisnegative" check causes FP divide by zero exceptions with any simple program that prints a double value, like:

printf("%f",(double)0.0);

When the divide by zero mask is disabled.

A better way to do the check would be to check the bits of the value to see if they're all "0x0", or not, by casting to an appropriate integer type.

Here's a simple reproducer:

#include <stdio.h>

main()
{
    short s;
    // Unmask div-by-zero, invalid, overflow
    __asm__("fstcw %0\n\t"
            "andw $0xf2, %0\n\t"
            "fldcw %0" : "+m" (s));
    printf("\n%f\n",(double)1.0); // this works
    printf("\n%f\n",(double)0.0); // this doesn't
}
Comment 1 Bernhard Reutner-Fischer 2014-12-15 13:08:03 UTC

*** This bug has been marked as a duplicate of bug 6152 ***