diff --git a/js/src/jsfun.c b/js/src/jsfun.c index f12a157c932..f7d699a0652 100644 --- a/js/src/jsfun.c +++ b/js/src/jsfun.c @@ -1,4 +1,5 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sw=4 et tw=80: * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 @@ -1710,6 +1711,10 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) principals = NULL; } + /* Belt-and-braces: check that the caller has access to parent. */ + if (!js_CheckPrincipalsAccess(cx, parent, principals, "Function")) + return JS_FALSE; + n = argc ? argc - 1 : 0; if (n > 0) { /* diff --git a/js/src/jsobj.c b/js/src/jsobj.c index 1fa9cdc5eac..d91d046b6da 100644 --- a/js/src/jsobj.c +++ b/js/src/jsobj.c @@ -1052,8 +1052,9 @@ obj_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) * if so (or if scopeobj has no principals, for backward compatibility with * the JS API, which does not require principals), and false otherwise. */ -static JSBool -CheckEvalAccess(JSContext *cx, JSObject *scopeobj, JSPrincipals *principals) +JSBool +js_CheckPrincipalsAccess(JSContext *cx, JSObject *scopeobj, + JSPrincipals *principals, const char *caller) { JSRuntime *rt; JSPrincipals *scopePrincipals; @@ -1064,18 +1065,25 @@ CheckEvalAccess(JSContext *cx, JSObject *scopeobj, JSPrincipals *principals) if (!principals || !scopePrincipals || !principals->subsume(principals, scopePrincipals)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_INDIRECT_CALL, js_eval_str); + JSMSG_BAD_INDIRECT_CALL, caller); return JS_FALSE; } } return JS_TRUE; } -JSBool +JSObject * js_CheckScopeChainValidity(JSContext *cx, JSObject *scopeobj, const char *caller) { JSClass *clasp; JSExtendedClass *xclasp; + JSObject *inner; + + OBJ_TO_INNER_OBJECT(cx, scopeobj); + if (!scopeobj) + return NULL; + + inner = scopeobj; /* XXX This is an awful gross hack. */ while (scopeobj) { @@ -1086,14 +1094,14 @@ js_CheckScopeChainValidity(JSContext *cx, JSObject *scopeobj, const char *caller xclasp->innerObject(cx, scopeobj) != scopeobj) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_INDIRECT_CALL, caller); - return JS_FALSE; + return NULL; } } scopeobj = OBJ_GET_PARENT(cx, scopeobj); } - return JS_TRUE; + return inner; } static JSBool @@ -1151,8 +1159,11 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) if (indirectCall) { callerScopeChain = caller->scopeChain; if (obj != callerScopeChain) { - if (!CheckEvalAccess(cx, obj, caller->script->principals)) + if (!js_CheckPrincipalsAccess(cx, obj, + caller->script->principals, + js_eval_str)) { return JS_FALSE; + } scopeobj = js_NewObject(cx, &js_WithClass, obj, callerScopeChain); @@ -1185,13 +1196,10 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) } /* Ensure we compile this eval with the right object in the scope chain. */ - OBJ_TO_INNER_OBJECT(cx, scopeobj); + scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_eval_str); if (!scopeobj) return JS_FALSE; - if (!js_CheckScopeChainValidity(cx, scopeobj, js_eval_str)) - return JS_FALSE; - str = JSVAL_TO_STRING(argv[0]); if (caller) { file = caller->script->filename; @@ -1239,7 +1247,7 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) * Belt-and-braces: check that the lesser of eval's principals and the * caller's principals has access to scopeobj. */ - ok = CheckEvalAccess(cx, scopeobj, principals); + ok = js_CheckPrincipalsAccess(cx, scopeobj, principals, js_eval_str); if (!ok) goto out; diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 616394c373b..68dfe5cab9f 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -488,9 +488,12 @@ js_GetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot); extern JSBool js_SetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot, jsval v); -extern JSBool +extern JSObject * js_CheckScopeChainValidity(JSContext *cx, JSObject *scopeobj, const char *caller); +extern JSBool +js_CheckPrincipalsAccess(JSContext *cx, JSObject *scopeobj, + JSPrincipals *principals, const char *caller); JS_END_EXTERN_C #endif /* jsobj_h___ */ diff --git a/js/src/jsscript.c b/js/src/jsscript.c index 23134e75f5a..698888a3993 100644 --- a/js/src/jsscript.c +++ b/js/src/jsscript.c @@ -65,6 +65,7 @@ #if JS_HAS_SCRIPT_OBJECT static const char js_script_exec[] = "Script.prototype.exec"; +static const char js_script_compile[] = "Script.prototype.compile"; #if JS_HAS_TOSOURCE static JSBool @@ -205,7 +206,7 @@ script_compile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, } /* Ensure we compile this script with the right (inner) principals. */ - OBJ_TO_INNER_OBJECT(cx, scopeobj); + scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_script_compile); if (!scopeobj) return JS_FALSE; @@ -248,7 +249,6 @@ script_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) JSObject *scopeobj, *parent; JSStackFrame *fp, *caller; JSPrincipals *principals, *scopePrincipals; - JSRuntime *rt; if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv)) return JS_FALSE; @@ -308,26 +308,14 @@ script_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) } } - OBJ_TO_INNER_OBJECT(cx, scopeobj); + scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_script_exec); if (!scopeobj) return JS_FALSE; - if (!js_CheckScopeChainValidity(cx, scopeobj, js_script_exec)) - return JS_FALSE; - /* Belt-and-braces: check that this script object has access to scopeobj. */ principals = script->principals; - rt = cx->runtime; - if (rt->findObjectPrincipals) { - scopePrincipals = rt->findObjectPrincipals(cx, scopeobj); - if (!principals || !scopePrincipals || - !principals->subsume(principals, scopePrincipals)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_INDIRECT_CALL, - js_script_exec); - return JS_FALSE; - } - } + if (!js_CheckPrincipalsAccess(cx, scopeobj, principals, js_script_exec)) + return JS_FALSE; return js_Execute(cx, scopeobj, script, caller, JSFRAME_EVAL, rval); }