Commit 8135caef authored by jgruber's avatar jgruber Committed by Commit bot

Make CallSite constructor inaccessible from JS

This type is not supposed to be constructable by users. Internally, we
use CallSiteUtils::Construct to create CallSite objects; and we simply
map a thrower builtin as the public CallSite constructor.

R=yangguo@chromium.org
BUG=

Review-Url: https://codereview.chromium.org/2201823002
Cr-Commit-Position: refs/heads/master@{#38234}
parent 962fd4ae
......@@ -2644,9 +2644,13 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
{ // -- C a l l S i t e
// Builtin functions for CallSite.
// CallSites are a special case; the constructor is for our private use
// only, therefore we set it up as a builtin that throws. Internally, we use
// CallSiteUtils::Construct to create CallSite objects.
Handle<JSFunction> callsite_fun = InstallFunction(
container, "CallSite", JS_OBJECT_TYPE, JSObject::kHeaderSize,
isolate->initial_object_prototype(), Builtins::kCallSiteConstructor);
isolate->initial_object_prototype(), Builtins::kUnsupportedThrower);
callsite_fun->shared()->DontAdaptArguments();
callsite_fun->shared()->set_native(true);
......
......@@ -22,21 +22,6 @@ namespace internal {
isolate->factory()->NewStringFromAsciiChecked(method))); \
}
BUILTIN(CallSiteConstructor) {
HandleScope scope(isolate);
Handle<JSFunction> target = args.target<JSFunction>();
Handle<Object> new_target = Handle<Object>::cast(args.new_target());
Handle<Object> receiver = args.atOrUndefined(isolate, 1);
Handle<Object> fun = args.atOrUndefined(isolate, 2);
Handle<Object> pos = args.atOrUndefined(isolate, 3);
Handle<Object> strict_mode = args.atOrUndefined(isolate, 4);
RETURN_RESULT_OR_FAILURE(
isolate, CallSiteUtils::Construct(isolate, target, new_target, receiver,
fun, pos, strict_mode));
}
namespace {
Object* PositiveNumberOrNull(int value, Isolate* isolate) {
......
......@@ -17,6 +17,12 @@ BUILTIN(Illegal) {
BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); }
BUILTIN(UnsupportedThrower) {
HandleScope scope(isolate);
THROW_NEW_ERROR_RETURN_FAILURE(isolate,
NewError(MessageTemplate::kUnsupported));
}
// -----------------------------------------------------------------------------
// Throwers for restricted function properties and strict arguments object
// properties
......
......@@ -184,6 +184,7 @@ namespace internal {
CPP(Illegal) \
CPP(RestrictedFunctionPropertiesThrower) \
CPP(RestrictedStrictArgumentsPropertiesThrower) \
CPP(UnsupportedThrower) \
\
/* Array */ \
ASM(ArrayCode) \
......@@ -213,7 +214,6 @@ namespace internal {
TFJ(BooleanPrototypeValueOf, 1) \
\
/* CallSite */ \
CPP(CallSiteConstructor) \
CPP(CallSitePrototypeGetColumnNumber) \
CPP(CallSitePrototypeGetEvalOrigin) \
CPP(CallSitePrototypeGetFileName) \
......
......@@ -431,13 +431,10 @@ Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
Handle<Object> pos,
Handle<Object> is_global) {
Isolate* isolate = fun->GetIsolate();
Handle<JSFunction> ctor =
handle(isolate->native_context()->callsite_function(), isolate);
Handle<Object> strict_mode = isolate->factory()->ToBoolean(false);
MaybeHandle<Object> maybe_callsite = CallSiteUtils::Construct(
isolate, ctor, ctor, recv, fun, pos, strict_mode);
MaybeHandle<Object> maybe_callsite =
CallSiteUtils::Construct(isolate, recv, fun, pos, strict_mode);
if (maybe_callsite.is_null()) {
isolate->clear_pending_exception();
return isolate->factory()->empty_string();
......
......@@ -509,9 +509,6 @@ MaybeHandle<FixedArray> GetStackFrames(Isolate* isolate,
FixedArray::get(*raw_stack_elements, 0, isolate);
int sloppy_frames = Handle<Smi>::cast(sloppy_frames_obj)->value();
Handle<JSFunction> callsite_ctor =
handle(isolate->native_context()->callsite_function(), isolate);
int dst_ix = 0;
Handle<FixedArray> frames = isolate->factory()->NewFixedArray(frame_count);
for (int i = 1; i < raw_stack_len; i += 4) {
......@@ -533,9 +530,7 @@ MaybeHandle<FixedArray> GetStackFrames(Isolate* isolate,
Handle<Object> callsite;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, callsite,
CallSiteUtils::Construct(isolate, callsite_ctor, callsite_ctor, recv,
fun, pos, strict),
FixedArray);
CallSiteUtils::Construct(isolate, recv, fun, pos, strict), FixedArray);
frames->set(dst_ix++, *callsite);
}
......@@ -889,19 +884,19 @@ MaybeHandle<String> ErrorUtils::ToString(Isolate* isolate,
target, isolate->factory()->key(), value, DONT_ENUM), \
Object)
MaybeHandle<Object> CallSiteUtils::Construct(
Isolate* isolate, Handle<JSFunction> target, Handle<Object> new_target,
Handle<Object> receiver, Handle<Object> fun, Handle<Object> pos,
Handle<Object> strict_mode) {
MaybeHandle<Object> CallSiteUtils::Construct(Isolate* isolate,
Handle<Object> receiver,
Handle<Object> fun,
Handle<Object> pos,
Handle<Object> strict_mode) {
// Create the JS object.
Handle<JSReceiver> new_target_recv =
new_target->IsJSReceiver() ? Handle<JSReceiver>::cast(new_target)
: Handle<JSReceiver>::cast(target);
Handle<JSFunction> target =
handle(isolate->native_context()->callsite_function(), isolate);
Handle<JSObject> obj;
ASSIGN_RETURN_ON_EXCEPTION(isolate, obj,
JSObject::New(target, new_target_recv), Object);
ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, JSObject::New(target, target),
Object);
// For wasm frames, receiver is the wasm object and fun is the function index
// instead of an actual function.
......@@ -916,10 +911,9 @@ MaybeHandle<Object> CallSiteUtils::Construct(
}
if (is_wasm_object) {
// TODO(jgruber): Convert back to DCHECK once the callsite constructor is
// inaccessible from JS.
CHECK(fun->IsSmi() && (wasm::GetNumberOfFunctions(JSObject::cast(
*receiver)) > Smi::cast(*fun)->value()));
DCHECK(fun->IsSmi());
DCHECK(wasm::GetNumberOfFunctions(JSObject::cast(*receiver)) >
Smi::cast(*fun)->value());
SET_CALLSITE_PROPERTY(obj, call_site_wasm_obj_symbol, receiver);
SET_CALLSITE_PROPERTY(obj, call_site_wasm_func_index_symbol, fun);
......@@ -929,10 +923,7 @@ MaybeHandle<Object> CallSiteUtils::Construct(
SET_CALLSITE_PROPERTY(obj, call_site_function_symbol, fun);
}
// TODO(jgruber): Convert back to DCHECK once the callsite constructor is
// inaccessible from JS.
CHECK(pos->IsSmi());
DCHECK(pos->IsSmi());
SET_CALLSITE_PROPERTY(obj, call_site_position_symbol, pos);
SET_CALLSITE_PROPERTY(
obj, call_site_strict_symbol,
......
......@@ -103,8 +103,6 @@ class ErrorUtils : public AllStatic {
class CallSiteUtils : public AllStatic {
public:
static MaybeHandle<Object> Construct(Isolate* isolate,
Handle<JSFunction> target,
Handle<Object> new_target,
Handle<Object> receiver,
Handle<Object> fun, Handle<Object> pos,
Handle<Object> strict_mode);
......
......@@ -398,8 +398,10 @@ assertThrows(() => Error.captureStackTrace(x));
// Check that we don't crash when CaptureSimpleStackTrace returns undefined.
var o = {};
var oldStackTraceLimit = Error.stackTraceLimit;
Error.stackTraceLimit = "not a number";
Error.captureStackTrace(o);
Error.stackTraceLimit = oldStackTraceLimit;
// Check that we don't crash when a callsite's function's script is empty.
Error.prepareStackTrace = function(e, frames) {
......@@ -412,14 +414,27 @@ try {
assertEquals(undefined, e.stack);
}
// Check that a tight recursion in prepareStackTrace fails gracefully, i.e.
// a range error is thrown and printed (but without showing the actual stack).
// Check that a tight recursion in prepareStackTrace throws when accessing
// stack. Trying again without a custom formatting function formats correctly.
var err = new Error("abc");
Error.prepareStackTrace = () => Error.prepareStackTrace();
try {
new Error().stack;
err.stack;
assertUnreachable();
} catch (e) {
assertTrue(
e.stack.indexOf("RangeError: Maximum call stack size exceeded") != -1);
assertTrue(e.stack.indexOf("prepareStackTrace") == -1);
err = e;
}
Error.prepareStackTrace = undefined;
assertTrue(
err.stack.indexOf("RangeError: Maximum call stack size exceeded") != -1);
assertTrue(err.stack.indexOf("prepareStackTrace") != -1);
// Check that the callsite constructor throws.
Error.prepareStackTrace = (e,s) => s;
var constructor = new Error().stack[0].constructor;
assertThrows(() => constructor.call());
assertThrows(() => constructor.call(
null, {}, () => undefined, {valueOf() { return 0 }}, false));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment