зеркало из https://github.com/mozilla/gecko-dev.git
- Don't cast malloc's return value, it's void *.
- Don't double-report a scanner error such as illegal character in Function("a@b", "return a*b") - Do report a "malformed formal parameter" error in Function("a,b,", "return a*b") - Fiddle comments to more precisely rule out the above bugs.
This commit is contained in:
Родитель
772e4db56c
Коммит
1cf65e15ec
|
@ -1437,9 +1437,11 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
* Allocate a string to hold the concatenated arguments, including room
|
* Allocate a string to hold the concatenated arguments, including room
|
||||||
* for a terminating 0.
|
* for a terminating 0.
|
||||||
*/
|
*/
|
||||||
cp = collected_args = (jschar *) JS_malloc(cx, (args_length + 1) *
|
cp = collected_args = JS_malloc(cx, (args_length + 1) * sizeof(jschar));
|
||||||
sizeof(jschar));
|
|
||||||
/* Concatenate the arguments into the new string, separated by commas. */
|
/*
|
||||||
|
* Concatenate the arguments into the new string, separated by commas.
|
||||||
|
*/
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
arg = JSVAL_TO_STRING(argv[i]);
|
arg = JSVAL_TO_STRING(argv[i]);
|
||||||
(void)js_strncpy(cp, arg->chars, arg->length);
|
(void)js_strncpy(cp, arg->chars, arg->length);
|
||||||
|
@ -1448,27 +1450,27 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
*(cp++) = (i + 1 < n) ? ',' : 0;
|
*(cp++) = (i + 1 < n) ? ',' : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make a tokenstream that reads from the given string. */
|
/*
|
||||||
ts = js_NewTokenStream(cx, collected_args, args_length, filename, lineno,
|
* Make a tokenstream that reads from the given string.
|
||||||
principals);
|
*/
|
||||||
|
ts = js_NewTokenStream(cx, collected_args, args_length, filename,
|
||||||
|
lineno, principals);
|
||||||
if (!ts) {
|
if (!ts) {
|
||||||
JS_free(cx, collected_args);
|
JS_free(cx, collected_args);
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
tt = js_GetToken(cx, ts);
|
|
||||||
/* The argument string may be empty or contain no tokens. */
|
/* The argument string may be empty or contain no tokens. */
|
||||||
|
tt = js_GetToken(cx, ts);
|
||||||
if (tt != TOK_EOF) {
|
if (tt != TOK_EOF) {
|
||||||
while (1) {
|
while (1) {
|
||||||
/*
|
/*
|
||||||
* Check that it's a name. This also implicitly guards against
|
* Check that it's a name. This also implicitly guards against
|
||||||
* TOK_ERROR.
|
* TOK_ERROR, which was already reported.
|
||||||
*/
|
*/
|
||||||
if (tt != TOK_NAME) {
|
if (tt != TOK_NAME)
|
||||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
goto bad_formal;
|
||||||
JSMSG_NO_FORMAL);
|
|
||||||
goto badargs;
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* Get the atom corresponding to the name from the tokenstream;
|
* Get the atom corresponding to the name from the tokenstream;
|
||||||
* we're assured at this point that it's a valid identifier.
|
* we're assured at this point that it's a valid identifier.
|
||||||
|
@ -1476,32 +1478,32 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
atom = ts->token.t_atom;
|
atom = ts->token.t_atom;
|
||||||
if (!js_LookupProperty(cx, obj, (jsid)atom, &obj2,
|
if (!js_LookupProperty(cx, obj, (jsid)atom, &obj2,
|
||||||
(JSProperty **)&sprop)) {
|
(JSProperty **)&sprop)) {
|
||||||
goto badargs;
|
goto bad_formal;
|
||||||
}
|
}
|
||||||
if (sprop && obj2 == obj) {
|
if (sprop && obj2 == obj) {
|
||||||
#ifdef CHECK_ARGUMENT_HIDING
|
#ifdef CHECK_ARGUMENT_HIDING
|
||||||
PR_ASSERT(sprop->getter == js_GetArgument);
|
PR_ASSERT(sprop->getter == js_GetArgument);
|
||||||
OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *)sprop);
|
OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *)sprop);
|
||||||
JS_ReportErrorNumber(cx, JSREPORT_WARNING,
|
JS_ReportErrorNumber(cx, JSREPORT_WARNING,
|
||||||
JSMSG_SAME_FORMAL, ATOM_BYTES(atom));
|
JSMSG_SAME_FORMAL, ATOM_BYTES(atom));
|
||||||
goto badargs;
|
goto bad_formal;
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
* A duplicate parameter name. We create a dummy symbol
|
* A duplicate parameter name. We create a dummy symbol
|
||||||
* entry with property id of the parameter number and set
|
* entry with property id of the parameter number and set
|
||||||
* the id to the name of the parameter.
|
* the id to the name of the parameter. See jsopcode.c:
|
||||||
* The decompiler will know to treat this case specially.
|
* the decompiler knows to treat this case specially.
|
||||||
*/
|
*/
|
||||||
jsid oldArgId = (jsid) sprop->id;
|
jsid oldArgId = (jsid) sprop->id;
|
||||||
OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *)sprop);
|
OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *)sprop);
|
||||||
sprop = NULL;
|
sprop = NULL;
|
||||||
if (!js_DefineProperty(cx, obj, oldArgId, JSVAL_VOID,
|
if (!js_DefineProperty(cx, obj, oldArgId, JSVAL_VOID,
|
||||||
js_GetArgument, js_SetArgument,
|
js_GetArgument, js_SetArgument,
|
||||||
JSPROP_ENUMERATE | JSPROP_PERMANENT,
|
JSPROP_ENUMERATE | JSPROP_PERMANENT,
|
||||||
(JSProperty **)&sprop)) {
|
(JSProperty **)&sprop)) {
|
||||||
goto badargs;
|
goto bad_formal;
|
||||||
}
|
}
|
||||||
sprop->id = (jsid) atom;
|
sprop->id = (jsid) atom;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (sprop)
|
if (sprop)
|
||||||
|
@ -1510,26 +1512,25 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
js_GetArgument, js_SetArgument,
|
js_GetArgument, js_SetArgument,
|
||||||
JSPROP_ENUMERATE | JSPROP_PERMANENT,
|
JSPROP_ENUMERATE | JSPROP_PERMANENT,
|
||||||
(JSProperty **)&sprop)) {
|
(JSProperty **)&sprop)) {
|
||||||
goto badargs;
|
goto bad_formal;
|
||||||
}
|
}
|
||||||
PR_ASSERT(sprop);
|
PR_ASSERT(sprop);
|
||||||
sprop->id = INT_TO_JSVAL(fun->nargs++);
|
sprop->id = INT_TO_JSVAL(fun->nargs++);
|
||||||
OBJ_DROP_PROPERTY(cx, obj, (JSProperty *)sprop);
|
OBJ_DROP_PROPERTY(cx, obj, (JSProperty *)sprop);
|
||||||
|
|
||||||
/* Done with the NAME; get the next token. */
|
/*
|
||||||
|
* Get the next token. Stop on end of stream. Otherwise
|
||||||
|
* insist on a comma, get another name, and iterate.
|
||||||
|
*/
|
||||||
tt = js_GetToken(cx, ts);
|
tt = js_GetToken(cx, ts);
|
||||||
/* Stop if we've reached the end of the string. */
|
|
||||||
if (tt == TOK_EOF)
|
if (tt == TOK_EOF)
|
||||||
break;
|
break;
|
||||||
|
if (tt != TOK_COMMA)
|
||||||
/*
|
goto bad_formal;
|
||||||
* If a comma is seen, get the next token. Otherwise, let the
|
tt = js_GetToken(cx, ts);
|
||||||
* loop catch the error.
|
|
||||||
*/
|
|
||||||
if (tt == TOK_COMMA)
|
|
||||||
tt = js_GetToken(cx, ts);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean up. */
|
/* Clean up. */
|
||||||
JS_free(cx, collected_args);
|
JS_free(cx, collected_args);
|
||||||
if (!js_CloseTokenStream(cx, ts))
|
if (!js_CloseTokenStream(cx, ts))
|
||||||
|
@ -1565,7 +1566,14 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
return js_ParseFunctionBody(cx, ts, fun) &&
|
return js_ParseFunctionBody(cx, ts, fun) &&
|
||||||
js_CloseTokenStream(cx, ts);
|
js_CloseTokenStream(cx, ts);
|
||||||
|
|
||||||
badargs:
|
bad_formal:
|
||||||
|
/*
|
||||||
|
* Report "malformed formal parameter" iff no illegal char or similar
|
||||||
|
* scanner error was already reported.
|
||||||
|
*/
|
||||||
|
if (!(ts->flags & TSF_ERROR))
|
||||||
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_FORMAL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clean up the arguments string and tokenstream if we failed to parse
|
* Clean up the arguments string and tokenstream if we failed to parse
|
||||||
* the arguments.
|
* the arguments.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче