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:
Tor Andersson
2014-02-27 13:49:22 +01:00
parent 43384d9110
commit 598de57d76
3 changed files with 61 additions and 3 deletions

View File

@@ -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)

View File

@@ -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;

View File

@@ -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);