зеркало из https://github.com/mozilla/pjs.git
Bug 106495: js_strtod and js_strtointeger no longer require \0-terminated js chars. r=brendan
This commit is contained in:
Родитель
b4938c5439
Коммит
8879b6dd6a
|
@ -97,11 +97,8 @@ num_parseFloat(JSContext *cx, uintN argc, jsval *vp)
|
|||
str = js_ValueToString(cx, vp[2]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
/* XXXbe js_strtod shouldn't require NUL termination */
|
||||
bp = js_UndependString(cx, str);
|
||||
if (!bp)
|
||||
return JS_FALSE;
|
||||
if (!js_strtod(cx, bp, &ep, &d))
|
||||
bp = JSSTRING_CHARS(str);
|
||||
if (!js_strtod(cx, bp, bp + JSSTRING_LENGTH(str), &ep, &d))
|
||||
return JS_FALSE;
|
||||
if (ep == bp) {
|
||||
*vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
|
||||
|
@ -133,11 +130,8 @@ num_parseInt(JSContext *cx, uintN argc, jsval *vp)
|
|||
str = js_ValueToString(cx, vp[2]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
/* XXXbe js_strtointeger shouldn't require NUL termination */
|
||||
bp = js_UndependString(cx, str);
|
||||
if (!bp)
|
||||
return JS_FALSE;
|
||||
if (!js_strtointeger(cx, bp, &ep, radix, &d))
|
||||
bp = JSSTRING_CHARS(str);
|
||||
if (!js_strtointeger(cx, bp, bp + JSSTRING_LENGTH(str), &ep, radix, &d))
|
||||
return JS_FALSE;
|
||||
if (ep == bp) {
|
||||
*vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
|
||||
|
@ -706,7 +700,7 @@ js_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp)
|
|||
{
|
||||
JSObject *obj;
|
||||
JSString *str;
|
||||
const jschar *bp, *ep;
|
||||
const jschar *bp, *end, *ep;
|
||||
|
||||
if (JSVAL_IS_OBJECT(v)) {
|
||||
obj = JSVAL_TO_OBJECT(v);
|
||||
|
@ -723,20 +717,19 @@ js_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp)
|
|||
*dp = *JSVAL_TO_DOUBLE(v);
|
||||
} else if (JSVAL_IS_STRING(v)) {
|
||||
str = JSVAL_TO_STRING(v);
|
||||
|
||||
/*
|
||||
* Note that ECMA doesn't treat a string beginning with a '0' as an
|
||||
* octal number here. This works because all such numbers will be
|
||||
* interpreted as decimal by js_strtod and will never get passed to
|
||||
* js_strtointeger (which would interpret them as octal).
|
||||
*/
|
||||
/* XXXbe js_strtod shouldn't require NUL termination */
|
||||
bp = js_UndependString(cx, str);
|
||||
if (!bp)
|
||||
return JS_FALSE;
|
||||
if ((!js_strtod(cx, bp, &ep, dp) ||
|
||||
js_SkipWhiteSpace(ep) != bp + str->length) &&
|
||||
(!js_strtointeger(cx, bp, &ep, 0, dp) ||
|
||||
js_SkipWhiteSpace(ep) != bp + str->length)) {
|
||||
bp = JSSTRING_CHARS(str);
|
||||
end = bp + JSSTRING_LENGTH(str);
|
||||
if ((!js_strtod(cx, bp, end, &ep, dp) ||
|
||||
js_SkipWhiteSpace(ep, end) != end) &&
|
||||
(!js_strtointeger(cx, bp, end, &ep, 0, dp) ||
|
||||
js_SkipWhiteSpace(ep, end) != end)) {
|
||||
goto badstr;
|
||||
}
|
||||
} else if (JSVAL_IS_BOOLEAN(v)) {
|
||||
|
@ -877,15 +870,18 @@ js_DoubleToInteger(jsdouble d)
|
|||
|
||||
|
||||
JSBool
|
||||
js_strtod(JSContext *cx, const jschar *s, const jschar **ep, jsdouble *dp)
|
||||
js_strtod(JSContext *cx, const jschar *s, const jschar *send,
|
||||
const jschar **ep, jsdouble *dp)
|
||||
{
|
||||
const jschar *s1;
|
||||
size_t length, i;
|
||||
char cbuf[32];
|
||||
size_t i;
|
||||
char *cstr, *istr, *estr;
|
||||
JSBool negative;
|
||||
jsdouble d;
|
||||
const jschar *s1 = js_SkipWhiteSpace(s);
|
||||
size_t length = js_strlen(s1);
|
||||
|
||||
s1 = js_SkipWhiteSpace(s, send);
|
||||
length = send - s1;
|
||||
|
||||
/* Use cbuf to avoid malloc */
|
||||
if (length >= sizeof cbuf) {
|
||||
|
@ -896,13 +892,12 @@ js_strtod(JSContext *cx, const jschar *s, const jschar **ep, jsdouble *dp)
|
|||
cstr = cbuf;
|
||||
}
|
||||
|
||||
for (i = 0; i <= length; i++) {
|
||||
if (s1[i] >> 8) {
|
||||
cstr[i] = 0;
|
||||
for (i = 0; i != length; i++) {
|
||||
if (s1[i] >> 8)
|
||||
break;
|
||||
}
|
||||
cstr[i] = (char)s1[i];
|
||||
}
|
||||
cstr[i] = 0;
|
||||
|
||||
istr = cstr;
|
||||
if ((negative = (*istr == '-')) != 0 || *istr == '+')
|
||||
|
@ -979,41 +974,54 @@ static intN GetNextBinaryDigit(struct BinaryDigitReader *bdr)
|
|||
}
|
||||
|
||||
JSBool
|
||||
js_strtointeger(JSContext *cx, const jschar *s, const jschar **ep, jsint base, jsdouble *dp)
|
||||
js_strtointeger(JSContext *cx, const jschar *s, const jschar *send,
|
||||
const jschar **ep, jsint base, jsdouble *dp)
|
||||
{
|
||||
const jschar *s1, *start;
|
||||
JSBool negative;
|
||||
jsdouble value;
|
||||
const jschar *start;
|
||||
const jschar *s1 = js_SkipWhiteSpace(s);
|
||||
|
||||
if ((negative = (*s1 == '-')) != 0 || *s1 == '+')
|
||||
s1 = js_SkipWhiteSpace(s, send);
|
||||
if (s1 == send)
|
||||
goto no_digits;
|
||||
if ((negative = (*s1 == '-')) != 0 || *s1 == '+') {
|
||||
s1++;
|
||||
if (s1 == send)
|
||||
goto no_digits;
|
||||
}
|
||||
|
||||
if (base == 0) {
|
||||
/* No base supplied, or some base that evaluated to 0. */
|
||||
if (*s1 == '0') {
|
||||
/* It's either hex or octal; only increment char if str isn't '0' */
|
||||
if (s1[1] == 'X' || s1[1] == 'x') { /* Hex */
|
||||
s1 += 2;
|
||||
if (s1 + 1 != send && (s1[1] == 'X' || s1[1] == 'x')) {
|
||||
base = 16;
|
||||
} else { /* Octal */
|
||||
s1 += 2;
|
||||
if (s1 == send)
|
||||
goto no_digits;
|
||||
} else {
|
||||
base = 8;
|
||||
}
|
||||
} else {
|
||||
base = 10; /* Default to decimal. */
|
||||
}
|
||||
} else if (base == 16 && *s1 == '0' && (s1[1] == 'X' || s1[1] == 'x')) {
|
||||
} else if (base == 16) {
|
||||
/* If base is 16, ignore hex prefix. */
|
||||
s1 += 2;
|
||||
if (*s1 == '0' && s1 + 1 != send && (s1[1] == 'X' || s1[1] == 'x')) {
|
||||
s1 += 2;
|
||||
if (s1 == send)
|
||||
goto no_digits;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Done with the preliminaries; find some prefix of the string that's
|
||||
* a number in the given base.
|
||||
*/
|
||||
start = s1; /* Mark - if string is empty, we return NaN. */
|
||||
JS_ASSERT(s1 < send);
|
||||
start = s1;
|
||||
value = 0.0;
|
||||
for (;;) {
|
||||
do {
|
||||
uintN digit;
|
||||
jschar c = *s1;
|
||||
if ('0' <= c && c <= '9')
|
||||
|
@ -1027,8 +1035,7 @@ js_strtointeger(JSContext *cx, const jschar *s, const jschar **ep, jsint base, j
|
|||
if (digit >= (uintN)base)
|
||||
break;
|
||||
value = value * base + digit;
|
||||
s1++;
|
||||
}
|
||||
} while (++s1 != send);
|
||||
|
||||
if (value >= 9007199254740992.0) {
|
||||
if (base == 10) {
|
||||
|
@ -1114,6 +1121,7 @@ js_strtointeger(JSContext *cx, const jschar *s, const jschar **ep, jsint base, j
|
|||
/* We don't worry about inaccurate numbers for any other base. */
|
||||
|
||||
if (s1 == start) {
|
||||
no_digits:
|
||||
*dp = 0.0;
|
||||
*ep = s;
|
||||
} else {
|
||||
|
|
|
@ -242,7 +242,8 @@ js_DoubleToInteger(jsdouble d);
|
|||
* Return false if out of memory.
|
||||
*/
|
||||
extern JSBool
|
||||
js_strtod(JSContext *cx, const jschar *s, const jschar **ep, jsdouble *dp);
|
||||
js_strtod(JSContext *cx, const jschar *s, const jschar *send,
|
||||
const jschar **ep, jsdouble *dp);
|
||||
|
||||
/*
|
||||
* Similar to strtol except that it handles integers of arbitrary size.
|
||||
|
@ -254,7 +255,8 @@ js_strtod(JSContext *cx, const jschar *s, const jschar **ep, jsdouble *dp);
|
|||
* Return false if out of memory.
|
||||
*/
|
||||
extern JSBool
|
||||
js_strtointeger(JSContext *cx, const jschar *s, const jschar **ep, jsint radix, jsdouble *dp);
|
||||
js_strtointeger(JSContext *cx, const jschar *s, const jschar *send,
|
||||
const jschar **ep, jsint radix, jsdouble *dp);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
|
|
|
@ -1119,6 +1119,7 @@ js_GetToken(JSContext *cx, JSTokenStream *ts)
|
|||
|
||||
/* The following 4 macros should only be used when TOKENBUF_OK() is true. */
|
||||
#define TOKENBUF_BASE() (ts->tokenbuf.base)
|
||||
#define TOKENBUF_END() (ts->tokenbuf.ptr)
|
||||
#define TOKENBUF_CHAR(i) (ts->tokenbuf.base[i])
|
||||
#define TRIM_TOKENBUF(i) (ts->tokenbuf.ptr = ts->tokenbuf.base + i)
|
||||
#define NUL_TERM_TOKENBUF() (*ts->tokenbuf.ptr = 0)
|
||||
|
@ -1443,14 +1444,16 @@ retry:
|
|||
if (!TOKENBUF_OK())
|
||||
goto error;
|
||||
if (radix == 10) {
|
||||
if (!js_strtod(cx, TOKENBUF_BASE(), &endptr, &dval)) {
|
||||
if (!js_strtod(cx, TOKENBUF_BASE(), TOKENBUF_END(),
|
||||
&endptr, &dval)) {
|
||||
js_ReportCompileErrorNumber(cx, ts,
|
||||
JSREPORT_TS | JSREPORT_ERROR,
|
||||
JSMSG_OUT_OF_MEMORY);
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
if (!js_strtointeger(cx, TOKENBUF_BASE(), &endptr, radix, &dval)) {
|
||||
if (!js_strtointeger(cx, TOKENBUF_BASE(), TOKENBUF_END(),
|
||||
&endptr, radix, &dval)) {
|
||||
js_ReportCompileErrorNumber(cx, ts,
|
||||
JSREPORT_TS | JSREPORT_ERROR,
|
||||
JSMSG_OUT_OF_MEMORY);
|
||||
|
|
|
@ -2861,10 +2861,10 @@ js_strchr_limit(const jschar *s, jschar c, const jschar *limit)
|
|||
}
|
||||
|
||||
const jschar *
|
||||
js_SkipWhiteSpace(const jschar *s)
|
||||
js_SkipWhiteSpace(const jschar *s, const jschar *end)
|
||||
{
|
||||
/* JS_ISSPACE is false on a null. */
|
||||
while (JS_ISSPACE(*s))
|
||||
JS_ASSERT(s <= end);
|
||||
while (s != end && JS_ISSPACE(*s))
|
||||
s++;
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -437,7 +437,7 @@ js_strchr_limit(const jschar *s, jschar c, const jschar *limit);
|
|||
* Return s advanced past any Unicode white space characters.
|
||||
*/
|
||||
extern const jschar *
|
||||
js_SkipWhiteSpace(const jschar *s);
|
||||
js_SkipWhiteSpace(const jschar *s, const jschar *end);
|
||||
|
||||
/*
|
||||
* Inflate bytes to JS chars and vice versa. Report out of memory via cx
|
||||
|
|
Загрузка…
Ссылка в новой задаче