mirror of
https://github.com/ccxvii/mujs.git
synced 2026-02-06 01:41:37 +08:00
Fix ToNumber from strings and parseInt and parseFloat.
Follow the spec more strictly, and don't rely on strtod's grammar. GNU libc strtod accepts 0x prefixes, INF, INFINITY and much more which we don't want, so pre-filter the string we pass to strtod.
This commit is contained in:
32
jsbuiltin.c
32
jsbuiltin.c
@@ -43,15 +43,43 @@ static void jsB_parseInt(js_State *J, unsigned int argc)
|
||||
{
|
||||
const char *s = js_tostring(J, 1);
|
||||
double radix = js_isdefined(J, 2) ? js_tonumber(J, 2) : 10;
|
||||
char *e;
|
||||
double n;
|
||||
|
||||
while (jsY_iswhite(*s) || jsY_isnewline(*s)) ++s;
|
||||
js_pushnumber(J, strtol(s, NULL, radix == 0 ? 10 : radix));
|
||||
if (radix == 0)
|
||||
radix = 10;
|
||||
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
|
||||
s += 2;
|
||||
radix = 16;
|
||||
}
|
||||
n = strtol(s, &e, radix);
|
||||
if (s == e)
|
||||
js_pushnumber(J, NAN);
|
||||
else
|
||||
js_pushnumber(J, n);
|
||||
}
|
||||
|
||||
static void jsB_parseFloat(js_State *J, unsigned int argc)
|
||||
{
|
||||
const char *s = js_tostring(J, 1);
|
||||
char *e;
|
||||
double n;
|
||||
|
||||
while (jsY_iswhite(*s) || jsY_isnewline(*s)) ++s;
|
||||
js_pushnumber(J, strtod(s, NULL));
|
||||
if (!strncmp(s, "Infinity", 8))
|
||||
js_pushnumber(J, INFINITY);
|
||||
else if (!strncmp(s, "+Infinity", 9))
|
||||
js_pushnumber(J, INFINITY);
|
||||
else if (!strncmp(s, "-Infinity", 9))
|
||||
js_pushnumber(J, -INFINITY);
|
||||
else {
|
||||
n = js_strtod(s, &e);
|
||||
if (e == s)
|
||||
js_pushnumber(J, NAN);
|
||||
else
|
||||
js_pushnumber(J, n);
|
||||
}
|
||||
}
|
||||
|
||||
static void jsB_isNaN(js_State *J, unsigned int argc)
|
||||
|
||||
31
jsvalue.c
31
jsvalue.c
@@ -110,6 +110,29 @@ int jsV_toboolean(js_State *J, const js_Value *v)
|
||||
}
|
||||
}
|
||||
|
||||
double js_strtod(const char *s, char **ep)
|
||||
{
|
||||
char *end;
|
||||
double n;
|
||||
const char *e = s;
|
||||
while (*e == '+' || *e == '-') ++e;
|
||||
while (*e >= '0' && *e <= '9') ++e;
|
||||
if (*e == '.') ++e;
|
||||
while (*e >= '0' && *e <= '9') ++e;
|
||||
if (*e == 'e' || *e == 'E') {
|
||||
++e;
|
||||
while (*e == '+' || *e == '-') ++e;
|
||||
while (*e >= '0' && *e <= '9') ++e;
|
||||
}
|
||||
n = strtod(s, &end);
|
||||
if (end == e) {
|
||||
*ep = (char*)e;
|
||||
return n;
|
||||
}
|
||||
*ep = (char*)s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ToNumber() on a string */
|
||||
double jsV_stringtonumber(js_State *J, const char *s)
|
||||
{
|
||||
@@ -118,8 +141,14 @@ double jsV_stringtonumber(js_State *J, const char *s)
|
||||
while (jsY_iswhite(*s) || jsY_isnewline(*s)) ++s;
|
||||
if (s[0] == '0' && s[1] == 'x' && s[2] != 0)
|
||||
n = strtol(s + 2, &e, 16);
|
||||
else if (!strncmp(s, "Infinity", 8))
|
||||
n = INFINITY, e = (char*)s + 8;
|
||||
else if (!strncmp(s, "+Infinity", 9))
|
||||
n = INFINITY, e = (char*)s + 9;
|
||||
else if (!strncmp(s, "-Infinity", 9))
|
||||
n = -INFINITY, e = (char*)s + 9;
|
||||
else
|
||||
n = strtod(s, &e);
|
||||
n = js_strtod(s, &e);
|
||||
while (jsY_iswhite(*e) || jsY_isnewline(*e)) ++e;
|
||||
if (*e) return NAN;
|
||||
return n;
|
||||
|
||||
@@ -123,6 +123,7 @@ const char *jsV_tostring(js_State *J, const js_Value *v);
|
||||
js_Object *jsV_toobject(js_State *J, const js_Value *v);
|
||||
js_Value jsV_toprimitive(js_State *J, const js_Value *v, int preferred);
|
||||
|
||||
double js_strtod(const char *s, char **ep);
|
||||
double jsV_numbertointeger(double n);
|
||||
int jsV_numbertoint32(double n);
|
||||
unsigned int jsV_numbertouint32(double n);
|
||||
|
||||
Reference in New Issue
Block a user