I found that pow() of glibc 2.2.4 causes stack overflow on some testcase with NaN operand. Try this simple (and dirty) test program (for little endian). main() { double x, y, z; *(int*)(&x) = 0x00000000; *((int*)(&x) + 1) = 0xfff00001; *(int*)(&y) = 0x80000000; *((int*)(&y) + 1) = 0xcff00000; z = pow(x, y); printf("%x %x\n", *((int*)&z + 1), *(int*)&z); return 0; } This program fall into endless recursive call at line 128 in sysdeps/ieee754/dbl-64/e_pow.c. 128: return (k==1)?__ieee754_pow(-x,y):-__ieee754_pow(-x,y); /* if y even or odd */ The problem occur if sign-bit of a NaN and negation of the NaN is same. I saw this problem only if the neg.d instruction was interpreted by kernel fp emulation. The patch below is a fix for kernel fp emulation. Is this a right fix? Or glibc should be fixed? --- Atsushi Nemoto
diff -u linux-sgi-cvs/arch/mips/math-emu/dp_simple.c linux.new/arch/mips/math-emu/dp_simple.c --- linux-sgi-cvs/arch/mips/math-emu/dp_simple.c Mon Oct 22 10:29:56 2001 +++ linux.new/arch/mips/math-emu/dp_simple.c Tue Feb 5 17:36:29 2002 @@ -48,16 +48,18 @@ CLEARCX; FLUSHXDP; + /* quick fix up */ + DPSIGN(x) ^= 1; + if (xc == IEEE754_CLASS_SNAN) { + ieee754dp y = ieee754dp_indef(); SETCX(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef(), "neg"); + DPSIGN(y) = DPSIGN(x); + return ieee754dp_nanxcpt(y, "neg"); } if (ieee754dp_isnan(x)) /* but not infinity */ return ieee754dp_nanxcpt(x, "neg", x); - - /* quick fix up */ - DPSIGN(x) ^= 1; return x; } diff -u linux-sgi-cvs/arch/mips/math-emu/sp_simple.c linux.new/arch/mips/math-emu/sp_simple.c --- linux-sgi-cvs/arch/mips/math-emu/sp_simple.c Mon Oct 22 10:29:56 2001 +++ linux.new/arch/mips/math-emu/sp_simple.c Tue Feb 5 17:36:29 2002 @@ -48,16 +48,18 @@ CLEARCX; FLUSHXSP; + /* quick fix up */ + SPSIGN(x) ^= 1; + if (xc == IEEE754_CLASS_SNAN) { + ieee754sp y = ieee754sp_indef(); SETCX(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef(), "neg"); + SPSIGN(y) = SPSIGN(x); + return ieee754sp_nanxcpt(y, "neg"); } if (ieee754sp_isnan(x)) /* but not infinity */ return ieee754sp_nanxcpt(x, "neg", x); - - /* quick fix up */ - SPSIGN(x) ^= 1; return x; }