summaryrefslogtreecommitdiffstats
path: root/js
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@wolfbeast.com>2019-03-22 12:06:40 +0100
committerwolfbeast <mcwerewolf@wolfbeast.com>2019-03-22 12:06:40 +0100
commita7013083d3620b683457d96c302c50a56f30e070 (patch)
tree80a13ea1cb37e9fbe9e05e2b52e1c25d84876683 /js
parentff9877cfe46e0c62e5e69af99445c7ca4738fbd5 (diff)
downloadUXP-a7013083d3620b683457d96c302c50a56f30e070.tar
UXP-a7013083d3620b683457d96c302c50a56f30e070.tar.gz
UXP-a7013083d3620b683457d96c302c50a56f30e070.tar.lz
UXP-a7013083d3620b683457d96c302c50a56f30e070.tar.xz
UXP-a7013083d3620b683457d96c302c50a56f30e070.zip
Check for dead wrappers in CallerGetterImpl/CallerSetterImpl.
This also removes code duplication by making CallerSetterImpl call CallerGetterImpl.
Diffstat (limited to 'js')
-rw-r--r--js/src/jsfun.cpp58
1 files changed, 12 insertions, 46 deletions
diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp
index 863871df9..98311be2f 100644
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -288,6 +288,12 @@ CallerGetterImpl(JSContext* cx, const CallArgs& args)
return true;
}
+ if (JS_IsDeadWrapper(callerObj)) {
+ JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
+ JSMSG_DEAD_OBJECT);
+ return false;
+ }
+
JSFunction* callerFun = &callerObj->as<JSFunction>();
MOZ_ASSERT(!callerFun->isBuiltin(), "non-builtin iterator returned a builtin?");
@@ -314,54 +320,14 @@ CallerSetterImpl(JSContext* cx, const CallArgs& args)
{
MOZ_ASSERT(IsFunction(args.thisv()));
- // Beware! This function can be invoked on *any* function! It can't
- // assume it'll never be invoked on natives, strict mode functions, bound
- // functions, or anything else that ordinarily has immutable .caller
- // defined with [[ThrowTypeError]].
- RootedFunction fun(cx, &args.thisv().toObject().as<JSFunction>());
- if (!CallerRestrictions(cx, fun))
- return false;
-
- // Return |undefined| unless an error must be thrown.
- args.rval().setUndefined();
-
- // We can almost just return |undefined| here -- but if the caller function
- // was strict mode code, we still have to throw a TypeError. This requires
- // computing the caller, checking that no security boundaries are crossed,
- // and throwing a TypeError if the resulting caller is strict.
-
- NonBuiltinScriptFrameIter iter(cx);
- if (!AdvanceToActiveCallLinear(cx, iter, fun))
- return true;
-
- ++iter;
- while (!iter.done() && iter.isEvalFrame())
- ++iter;
-
- if (iter.done() || !iter.isFunctionFrame())
- return true;
-
- RootedObject caller(cx, iter.callee(cx));
- if (!cx->compartment()->wrap(cx, &caller)) {
- cx->clearPendingException();
- return true;
- }
-
- // If we don't have full access to the caller, or the caller is not strict,
- // return undefined. Otherwise throw a TypeError.
- JSObject* callerObj = CheckedUnwrap(caller);
- if (!callerObj)
- return true;
-
- JSFunction* callerFun = &callerObj->as<JSFunction>();
- MOZ_ASSERT(!callerFun->isBuiltin(), "non-builtin iterator returned a builtin?");
-
- if (callerFun->strict()) {
- JS_ReportErrorFlagsAndNumberASCII(cx, JSREPORT_ERROR, GetErrorMessage, nullptr,
- JSMSG_CALLER_IS_STRICT);
- return false;
+ // We just have to return |undefined|, but first we call CallerGetterImpl
+ // because we need the same strict-mode and security checks.
+
+ if (!CallerGetterImpl(cx, args)) {
+ return false;
}
+ args.rval().setUndefined();
return true;
}