Protect js_ConstructObject callers from gc hazards and some other stuff. bug 325425, r=igor sr=brendan

This commit is contained in:
mrbkap%gmail.com 2006-02-07 20:09:53 +00:00
parent f4445bd103
commit 7d72129844
2 changed files with 34 additions and 8 deletions

View File

@ -286,3 +286,4 @@ MSG_DEF(JSMSG_BAD_SURROGATE_CHAR, 203, 1, JSEXN_TYPEERR, "bad surrogate char
MSG_DEF(JSMSG_UTF8_CHAR_TOO_LARGE, 204, 1, JSEXN_TYPEERR, "UTF-8 character {0} too large")
MSG_DEF(JSMSG_MALFORMED_UTF8_CHAR, 205, 1, JSEXN_TYPEERR, "malformed UTF-8 character sequence at offset {0}")
MSG_DEF(JSMSG_USER_DEFINED_ERROR, 206, 0, JSEXN_ERR, "JS_ReportError was called")
MSG_DEF(JSMSG_WRONG_CONSTRUCTOR, 207, 1, JSEXN_TYPEERR, "wrong construtor called for {0}")

View File

@ -2126,13 +2126,18 @@ js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent, uintN argc, jsval *argv)
{
jsval cval, rval;
JSTempValueRooter tvr;
JSTempValueRooter argtvr, tvr;
JSObject *obj, *ctor;
if (!js_FindConstructor(cx, parent, clasp->name, &cval))
JS_PUSH_TEMP_ROOT(cx, argc, argv, &argtvr);
if (!js_FindConstructor(cx, parent, clasp->name, &cval)) {
JS_POP_TEMP_ROOT(cx, &argtvr);
return NULL;
}
if (JSVAL_IS_PRIMITIVE(cval)) {
js_ReportIsNotFunction(cx, &cval, JSV2F_CONSTRUCT | JSV2F_SEARCH_STACK);
JS_POP_TEMP_ROOT(cx, &argtvr);
return NULL;
}
@ -2141,7 +2146,6 @@ js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
* this point, all control flow must exit through label out with obj set.
*/
JS_PUSH_SINGLE_TEMP_ROOT(cx, cval, &tvr);
obj = NULL;
/*
* If proto or parent are NULL, set them to Constructor.prototype and/or
@ -2155,6 +2159,7 @@ js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
ATOM_TO_JSID(cx->runtime->atomState
.classPrototypeAtom),
&rval)) {
obj = NULL;
goto out;
}
if (JSVAL_IS_OBJECT(rval))
@ -2165,17 +2170,37 @@ js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
if (!obj)
goto out;
if (!js_InternalConstruct(cx, obj, cval, argc, argv, &rval)) {
cx->newborn[GCX_OBJECT] = NULL;
obj = NULL;
if (!js_InternalConstruct(cx, obj, cval, argc, argv, &rval))
goto bad;
if (JSVAL_IS_PRIMITIVE(rval))
goto out;
obj = JSVAL_TO_OBJECT(rval);
/*
* If the given class has both the JSCLASS_HAS_PRIVATE and the
* JSCLASS_CONSTRUCT_PROTOTYPE flags, then the class should have its private
* data set. If it doesn't, then it means the constructor was replaced, and
* we should throw a typerr.
*/
if (OBJ_GET_CLASS(cx, obj) != clasp ||
(!(~clasp->flags & (JSCLASS_HAS_PRIVATE |
JSCLASS_CONSTRUCT_PROTOTYPE)) &&
!JS_GetPrivate(cx, obj))) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_WRONG_CONSTRUCTOR, clasp->name);
goto bad;
}
if (!JSVAL_IS_PRIMITIVE(rval))
obj = JSVAL_TO_OBJECT(rval);
out:
JS_POP_TEMP_ROOT(cx, &tvr);
JS_POP_TEMP_ROOT(cx, &argtvr);
return obj;
bad:
cx->newborn[GCX_OBJECT] = NULL;
obj = NULL;
goto out;
}
void