Subj : Re: JSVAL_IS_NUMBER(NaN) == TRUE (!?) To : netscape.public.mozilla.jseng From : Rob Swindell Date : Fri Feb 25 2005 11:03 pm I've upgraded to the latest code from cvs-mirror.mozilla.org (JavaScript-C 1.5 pre-release 6a 2004-06-09) and JS_ValueToInt32(jsval = NaN) is still crashing the same way (assertion in jsopcode.c, line 1906): case JSOP_GETARG: atom = GetSlotAtom(jp, js_GetArgument, GET_ARGNO(pc)); LOCAL_ASSERT(atom); <--- asserting here goto do_name; Here's a copy of the callstack at the time of the assertion: NTDLL! 77f813b1() Decompile(SprintStack * 0x02e2c1e8, unsigned char * 0x035961f2, int 0x00000003) line 1906 + 46 bytes js_DecompileCode(JSPrinter * 0x03a2ebb0, JSScript * 0x03596128, unsigned char * 0x035961f2, unsigned int 0x00000003) line 2557 + 17 bytes js_DecompileValueGenerator(JSContext * 0x02b35460, int 0x00000001, long 0x02933782, JSString * 0x00000000) line 2896 + 21 bytes js_ValueToInt32(JSContext * 0x02b35460, long 0x02933782, long * 0x02e2c5d8) line 840 + 17 bytes JS_ValueToInt32(JSContext * 0x02b35460, long 0x02933782, long * 0x02e2c5d8) line 578 + 17 bytes js_get_msg_header(JSContext * 0x02b35460, JSObject * 0x03a00b60, unsigned int 0x00000002, long * 0x0358ec18, long* 0x02e2ca9c) line 643 + 32 bytes js_Invoke(JSContext * 0x02b35460, unsigned int 0x00000002, unsigned int 0x00000000) line 1293 + 26 bytes js_Interpret(JSContext * 0x02b35460, unsigned char * 0x035961f5, long * 0x02e2db2c) line 3566 + 15 bytes js_Execute(JSContext * 0x02b35460, JSObject * 0x029337a8, JSScript * 0x0358df38, JSStackFrame * 0x00000000, unsigned int 0x00000000, long * 0x02e2e164) line 1523 + 19 bytes JS_ExecuteScript(JSContext * 0x02b35460, JSObject * 0x029337a8, JSScript * 0x0358df38, long * 0x02e2e164) line 3630 + 25 bytes exec_ssjs(http_session_t * 0x02e2e234, char * 0x02e2e351) line 2758 + 36 bytes respond(http_session_t * 0x02e2e234) line 2809 + 18 bytes http_session_thread(void * 0x00000000) line 2943 + 12 bytes _threadstart(void * 0x00d73b38) line 187 + 13 bytes -Rob > What goes wrong if you let NaNs flow through, as Math.sin and all the > rest do, and have done, since 1995? > > > > These functions attempt to convert a "number" argument to an integer using > > JS_ValueToInt32(). The test for a "number" was done using JSVAL_IS_NUMBER, > > which if the value is NaN, can't logically produce a valid int32 value. I don't > > know if this is the reason, but js32.dll v1.5 pre-release 5a (the version used > > in the current release of my product) will crash if NaN is passed to > > JS_ValueToInt32. Here's an example callstack of one such crash: > > > > NTDLL! 77f813b1() > > Decompile(SprintStack * 0x035dc4b0, unsigned char * 0x03eaf4ce, int 0x00000003) > > line 1860 + 47 bytes > > js_DecompileCode(JSPrinter * 0x05622208, JSScript * 0x03eaf400, unsigned char * > > 0x03eaf4ce, unsigned int 0x00000003) line 2347 + 17 bytes > > js_DecompileValueGenerator(JSContext * 0x02f42b70, int 0x00000001, long > > 0x030b6322, JSString * 0x00000000) line 2669 + 27 bytes > > js_ValueToInt32(JSContext * 0x02f42b70, long 0x030b6322, long * 0x035dc89c) > > line 765 + 17 bytes > > JS_ValueToInt32(JSContext * 0x02f42b70, long 0x030b6322, long * 0x035dc89c) > > line 552 + 17 bytes > > js_get_msg_header(JSContext * 0x02f42b70, JSObject * 0x055f13a0, unsigned int > > 0x00000002, long * 0x03ea401c, long * 0x035dcd48) line 643 + 32 bytes > > js_Invoke(JSContext * 0x02f42b70, unsigned int 0x00000002, unsigned int > > 0x00000000) line 843 + 26 bytes > > js_Interpret(JSContext * 0x02f42b70, long * 0x035de164) line 2852 + 15 bytes > > js_Execute(JSContext * 0x02f42b70, JSObject * 0x030b6340, JSScript * > > 0x03ea3700, JSStackFrame * 0x00000000, unsigned int 0x00000000, long * > > 0x035de164) line 1055 + 13 bytes > > JS_ExecuteScript(JSContext * 0x02f42b70, JSObject * 0x030b6340, JSScript * > > 0x03ea3700, long * 0x035de164) line 3373 + 25 bytes > > exec_ssjs(http_session_t * 0x035de234, char * 0x035de351) line 2758 + 36 bytes > > respond(http_session_t * 0x035de234) line 2809 + 18 bytes > > http_session_thread(void * 0x00000000) line 2943 + 12 bytes > > _threadstart(void * 0x050286f0) line 187 + 13 bytes > > KERNEL32! 7c57b388() > > > > I don't know whether it *should* be legal for JS_ValueToInt32() to convert a > > NaN jsval or not, > > > It should be possible, because (see jsnum.c) js_ValueToInt32 checks > JSDOUBLE_IS_NaN and reports an error. In the older version of the > engine you are using, that seems to crash, but I don't have a copy of > that older version to test. > > If you can't upgrade to a newer version of the engine (RC5a is quite > old), then mail me the source line and a few lines of surrounding > context, and the bad pointer or whatever, at the crash site in > Decompile, and I'll see if I can help (first by finding the bug with a > fix-patch that corrected this problem). > > > > but in any case, it's not what I intended this method to do > > if passed such a value. It instead should return the proper error result, as it > > does now, using the JSVAL_IS_NUM() macro to test for a valid number value (not > > including NaN). > > > What's the proper error result, if not an exception (as you'd get from > the error reported by js_ValueToInt32 if the Decompile bug were fixed)? > > > > I'm assuming the root cause of the above crash has been fixed in later versions > > of SpiderMonkey as tests conducted with newer libjs.so's (for Linux and > > FreeBSD) did not crash. But the crash highlighted the fact my methods were > > attempting to process the passed value as a valid number, when in fact it was > > not. > > > No, they were attempting to report an error converting NaN to "Int32", > so they were trying to "return the proper error result" (at least in the > JS_ValueToInt32 sense). > > Doing your own custom error handling may be better, but at first blush > it seems to me that you would want to use the same input validation that > JS_Convert* and JS_ValueToInt32 use. > > /be .