ref: 32ac46df1537af92a08377fe4ac31b55fa759a59
parent: 7562052e872fe33f55834e1b72c8e4969fb83b1c
author: Tor Andersson <tor@ccxvii.net>
date: Wed Feb 26 10:58:02 EST 2014
Fix relational equality with NaN.
--- a/js.h
+++ b/js.h
@@ -159,7 +159,7 @@
void js_replace(js_State* J, int idx);
void js_concat(js_State *J);
-int js_compare(js_State *J);
+int js_compare(js_State *J, int *okay);
int js_equal(js_State *J);
int js_strictequal(js_State *J);
int js_instanceof(js_State *J);
--- a/jsrun.c
+++ b/jsrun.c
@@ -1000,7 +1000,7 @@
js_Object *obj;
double x, y;
unsigned int ux, uy;
- int ix, iy;
+ int ix, iy, okay;
int b;
while (1) {
@@ -1315,10 +1315,10 @@
/* Relational operators */
- case OP_LT: b = js_compare(J); js_pop(J, 2); js_pushboolean(J, b < 0); break;
- case OP_GT: b = js_compare(J); js_pop(J, 2); js_pushboolean(J, b > 0); break;
- case OP_LE: b = js_compare(J); js_pop(J, 2); js_pushboolean(J, b <= 0); break;
- case OP_GE: b = js_compare(J); js_pop(J, 2); js_pushboolean(J, b >= 0); break;
+ case OP_LT: b = js_compare(J, &okay); js_pop(J, 2); js_pushboolean(J, okay && b < 0); break;
+ case OP_GT: b = js_compare(J, &okay); js_pop(J, 2); js_pushboolean(J, okay && b > 0); break;
+ case OP_LE: b = js_compare(J, &okay); js_pop(J, 2); js_pushboolean(J, okay && b <= 0); break;
+ case OP_GE: b = js_compare(J, &okay); js_pop(J, 2); js_pushboolean(J, okay && b >= 0); break;
case OP_INSTANCEOF:
b = js_instanceof(J);
--- a/jsvalue.c
+++ b/jsvalue.c
@@ -368,16 +368,19 @@
}
}
-int js_compare(js_State *J)
+int js_compare(js_State *J, int *okay)
{
js_Value va = js_toprimitive(J, -2, JS_HNUMBER);
js_Value vb = js_toprimitive(J, -1, JS_HNUMBER);
+ *okay = 1;
if (va.type == JS_TSTRING && vb.type == JS_TSTRING) {
return strcmp(va.u.string, vb.u.string);
} else {
double x = jsV_tonumber(J, &va);
double y = jsV_tonumber(J, &vb);
+ if (isnan(x) || isnan(y))
+ *okay = 0;
return x < y ? -1 : x > y ? 1 : 0;
}
}