b69c3770b2
This CL plugs the hole in the outside<-ShadowRealm direction (i.e. getting a reference to an object inside of the ShadowRealm from outside the ShadowRealm). This is a follow-on CL to https://chromium-review.googlesource.com/c/v8/v8/+/4108810, which plugged the getFunction hole in the ShadowRealm<-outside direction (i.e. getting a reference to an object outside of the ShadowRealm from inside the ShadowRealm). Bug: v8:1198 Change-Id: Ic06533ba8b1cc6477ef9d55a23cb8b0b6584d4a6 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4115657 Commit-Queue: Shu-yu Guo <syg@chromium.org> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Auto-Submit: Shu-yu Guo <syg@chromium.org> Cr-Commit-Position: refs/heads/main@{#85003}
115 lines
3.0 KiB
JavaScript
115 lines
3.0 KiB
JavaScript
// Copyright 2022 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// Flags: --harmony-shadow-realm
|
|
|
|
// Test that CallSite#getFunction and CallSite#getThis throw inside ShadowRealms
|
|
// and cannot access objects from the outside, as otherwise we could violate the
|
|
// callable boundary invariant.
|
|
(function testInside() {
|
|
const shadowRealm = new ShadowRealm();
|
|
|
|
// The ShadowRealm won't have assertThrows, so use try-catch and accumulate a
|
|
// message string.
|
|
const wrapped = shadowRealm.evaluate(`
|
|
Error.prepareStackTrace = function(err, frames) {
|
|
let a = [];
|
|
for (let i = 0; i < frames.length; i++) {
|
|
try {
|
|
a.push(frames[i].getFunction());
|
|
} catch (e) {
|
|
a.push("getFunction threw");
|
|
}
|
|
try {
|
|
a.push(frames[i].getThis());
|
|
} catch (e) {
|
|
a.push("getThis threw");
|
|
}
|
|
}
|
|
return a.join(' ');
|
|
};
|
|
|
|
function inner() {
|
|
try {
|
|
throw new Error();
|
|
} catch (e) {
|
|
return e.stack;
|
|
}
|
|
}
|
|
|
|
inner;
|
|
`);
|
|
|
|
(function outer() {
|
|
// There are 4 frames, youngest to oldest:
|
|
//
|
|
// inner
|
|
// outer
|
|
// testInside
|
|
// top-level
|
|
//
|
|
// So getFunction/getThis should throw 4 times since the prepareStackTrace
|
|
// hook is executing inside the ShadowRealm.
|
|
assertEquals("getFunction threw getThis threw " +
|
|
"getFunction threw getThis threw " +
|
|
"getFunction threw getThis threw " +
|
|
"getFunction threw getThis threw", wrapped());
|
|
})();
|
|
})();
|
|
|
|
// Test that CallSite#getFunction and CallSite#getThis throw for ShadowRealm
|
|
// objects from the outside, as otherwise we can also violate the callable
|
|
// boundary.
|
|
(function testOutside() {
|
|
Error.prepareStackTrace = function(err, frames) {
|
|
let a = [];
|
|
for (let i = 0; i < frames.length; i++) {
|
|
try {
|
|
frames[i].getFunction();
|
|
a.push(`functionName: ${frames[i].getFunctionName()}`);
|
|
} catch (e) {
|
|
a.push(`${frames[i].getFunctionName()} threw`);
|
|
}
|
|
try {
|
|
frames[i].getThis();
|
|
a.push("t");
|
|
} catch (e) {
|
|
a.push("getThis threw");
|
|
}
|
|
}
|
|
return JSON.stringify(a);
|
|
};
|
|
const shadowRealm = new ShadowRealm();
|
|
const wrap = shadowRealm.evaluate(`
|
|
function trampolineMaker(callback) {
|
|
return function trampoline() { return callback(); };
|
|
}
|
|
trampolineMaker;
|
|
`);
|
|
const wrapped = wrap(function callback() {
|
|
try {
|
|
throw new Error();
|
|
} catch (e) {
|
|
return e.stack;
|
|
}
|
|
});
|
|
|
|
|
|
// There are 4 frames, youngest to oldest:
|
|
//
|
|
// callback (in outer realm)
|
|
// trampoline (in ShadowRealm)
|
|
// testOutside (in outer realm)
|
|
// top-level (in outer realm)
|
|
//
|
|
// The frame corresponding to trampoline should throw, since the outer realm
|
|
// should not get references to ShadowRealm objects.
|
|
assertEquals(JSON.stringify(
|
|
["functionName: callback", "t",
|
|
"trampoline threw", "getThis threw",
|
|
"functionName: testOutside", "t",
|
|
"functionName: null", "t"]), wrapped());
|
|
assertEquals
|
|
})();
|