Commit 12bcba15 authored by bmeurer's avatar bmeurer Committed by Commit bot

[builtins] Sanitize receiver patching for API functions.

The API functions are always in sloppy mode, so receiver is always a
JSReceiver once the actual call trampoline runs, no need to check again
in various places.

R=verwaest@chromium.org

Review URL: https://codereview.chromium.org/1575973006

Cr-Commit-Position: refs/heads/master@{#33258}
parent 4e509c23
......@@ -1212,10 +1212,6 @@ static void CompatibleReceiverCheck(MacroAssembler* masm, Register receiver,
Register map = scratch1;
Register constructor = scratch2;
// If the receiver is not an object, jump to receiver_check_failed.
__ CompareObjectType(receiver, map, ip, FIRST_JS_OBJECT_TYPE);
__ b(lo, receiver_check_failed);
// If there is no signature, return the holder.
__ ldr(signature, FieldMemOperand(function_template_info,
FunctionTemplateInfo::kSignatureOffset));
......@@ -1284,21 +1280,13 @@ void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) {
// -- sp[4 * argc] : receiver
// -----------------------------------
// Load the receiver.
__ ldr(r2, MemOperand(sp, r0, LSL, kPointerSizeLog2));
// Update the receiver if this is a contextual call.
Label set_global_proxy, valid_receiver;
__ CompareRoot(r2, Heap::kUndefinedValueRootIndex);
__ b(eq, &set_global_proxy);
__ bind(&valid_receiver);
// Load the FunctionTemplateInfo.
__ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
__ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kFunctionDataOffset));
// Do the compatible receiver check.
Label receiver_check_failed;
__ ldr(r2, MemOperand(sp, r0, LSL, kPointerSizeLog2));
CompatibleReceiverCheck(masm, r2, r3, r4, r5, r6, &receiver_check_failed);
// Get the callback offset from the FunctionTemplateInfo, and jump to the
......@@ -1308,11 +1296,6 @@ void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) {
__ add(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(r4);
__ bind(&set_global_proxy);
__ LoadGlobalProxy(r2);
__ str(r2, MemOperand(sp, r0, LSL, kPointerSizeLog2));
__ b(&valid_receiver);
// Compatible receiver check failed: throw an Illegal Invocation exception.
__ bind(&receiver_check_failed);
// Drop the arguments (including the receiver)
......
......@@ -1191,10 +1191,6 @@ static void CompatibleReceiverCheck(MacroAssembler* masm, Register receiver,
Register map = scratch1;
Register constructor = scratch2;
// If the receiver is not an object, jump to receiver_check_failed.
__ CompareObjectType(receiver, map, x16, FIRST_JS_OBJECT_TYPE);
__ B(lo, receiver_check_failed);
// If there is no signature, return the holder.
__ Ldr(signature, FieldMemOperand(function_template_info,
FunctionTemplateInfo::kSignatureOffset));
......@@ -1263,21 +1259,13 @@ void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) {
// -- sp[8 * argc] : receiver
// -----------------------------------
// Load the receiver.
__ Ldr(x2, MemOperand(jssp, x0, LSL, kPointerSizeLog2));
// Update the receiver if this is a contextual call.
Label set_global_proxy, valid_receiver;
__ CompareRoot(x2, Heap::kUndefinedValueRootIndex);
__ B(eq, &set_global_proxy);
__ Bind(&valid_receiver);
// Load the FunctionTemplateInfo.
__ Ldr(x3, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
__ Ldr(x3, FieldMemOperand(x3, SharedFunctionInfo::kFunctionDataOffset));
// Do the compatible receiver check.
Label receiver_check_failed;
__ Ldr(x2, MemOperand(jssp, x0, LSL, kPointerSizeLog2));
CompatibleReceiverCheck(masm, x2, x3, x4, x5, x6, &receiver_check_failed);
// Get the callback offset from the FunctionTemplateInfo, and jump to the
......@@ -1287,11 +1275,6 @@ void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) {
__ Add(x4, x4, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(x4);
__ Bind(&set_global_proxy);
__ LoadGlobalProxy(x2);
__ Str(x2, MemOperand(jssp, x0, LSL, kPointerSizeLog2));
__ B(&valid_receiver);
// Compatible receiver check failed: throw an Illegal Invocation exception.
__ Bind(&receiver_check_failed);
// Drop the arguments (including the receiver)
......
......@@ -3370,6 +3370,7 @@ MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(
Isolate* isolate, BuiltinArguments<BuiltinExtraArguments::kTarget> args) {
HandleScope scope(isolate);
Handle<JSFunction> function = args.target();
DCHECK(args.receiver()->IsJSReceiver());
// TODO(ishell): turn this back to a DCHECK.
CHECK(function->shared()->IsApiFunction());
......@@ -3383,11 +3384,8 @@ MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(
Object);
}
DCHECK(!args[0]->IsNull());
if (args[0]->IsUndefined()) args[0] = function->global_proxy();
if (!is_construct && !fun_data->accept_any_receiver()) {
Handle<Object> receiver(&args[0]);
Handle<JSReceiver> receiver = args.at<JSReceiver>(0);
if (receiver->IsJSObject() && receiver->IsAccessCheckNeeded()) {
Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver);
if (!isolate->MayAccess(handle(isolate->context()), js_receiver)) {
......
......@@ -2247,10 +2247,6 @@ static void CompatibleReceiverCheck(MacroAssembler* masm, Register receiver,
Register function_template_info,
Register scratch0, Register scratch1,
Label* receiver_check_failed) {
// If receiver is not an object, jump to receiver_check_failed.
__ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, scratch0);
__ j(below, receiver_check_failed);
// If there is no signature, return the holder.
__ CompareRoot(FieldOperand(function_template_info,
FunctionTemplateInfo::kSignatureOffset),
......@@ -2324,22 +2320,13 @@ void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) {
// -- esp[(eax + 1) * 4] : receiver
// -----------------------------------
// Load the receiver.
Operand receiver_operand(esp, eax, times_pointer_size, kPCOnStackSize);
__ mov(ecx, receiver_operand);
// Update the receiver if this is a contextual call.
Label set_global_proxy, valid_receiver;
__ CompareRoot(ecx, Heap::kUndefinedValueRootIndex);
__ j(equal, &set_global_proxy);
__ bind(&valid_receiver);
// Load the FunctionTemplateInfo.
__ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
__ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kFunctionDataOffset));
// Do the compatible receiver check.
Label receiver_check_failed;
__ mov(ecx, Operand(esp, eax, times_pointer_size, kPCOnStackSize));
__ Push(eax);
CompatibleReceiverCheck(masm, ecx, ebx, edx, eax, &receiver_check_failed);
__ Pop(eax);
......@@ -2350,12 +2337,6 @@ void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) {
__ add(edx, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ jmp(edx);
__ bind(&set_global_proxy);
__ mov(ecx, NativeContextOperand());
__ mov(ecx, ContextOperand(ecx, Context::GLOBAL_PROXY_INDEX));
__ mov(receiver_operand, ecx);
__ jmp(&valid_receiver, Label::kNear);
// Compatible receiver check failed: pop return address, arguments and
// receiver and throw an Illegal Invocation exception.
__ bind(&receiver_check_failed);
......
......@@ -1226,10 +1226,6 @@ static void CompatibleReceiverCheck(MacroAssembler* masm, Register receiver,
Register constructor = t4;
Register scratch = t5;
// If the receiver is not an object, jump to receiver_check_failed.
__ GetObjectType(receiver, map, scratch);
__ Branch(receiver_check_failed, lo, scratch, Operand(FIRST_JS_OBJECT_TYPE));
// If there is no signature, return the holder.
__ lw(signature, FieldMemOperand(function_template_info,
FunctionTemplateInfo::kSignatureOffset));
......@@ -1296,22 +1292,15 @@ void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) {
// -- sp[4 * argc] : receiver
// -----------------------------------
// Load the receiver.
__ sll(at, a0, kPointerSizeLog2);
__ Addu(t8, sp, at);
__ lw(t0, MemOperand(t8));
// Update the receiver if this is a contextual call.
Label set_global_proxy, valid_receiver;
__ JumpIfRoot(t0, Heap::kUndefinedValueRootIndex, &set_global_proxy);
// Load the FunctionTemplateInfo.
__ bind(&valid_receiver);
__ lw(t1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ lw(t1, FieldMemOperand(t1, SharedFunctionInfo::kFunctionDataOffset));
// Do the compatible receiver check.
Label receiver_check_failed;
__ sll(at, a0, kPointerSizeLog2);
__ Addu(t8, sp, at);
__ lw(t0, MemOperand(t8));
CompatibleReceiverCheck(masm, t0, t1, &receiver_check_failed);
// Get the callback offset from the FunctionTemplateInfo, and jump to the
......@@ -1321,11 +1310,6 @@ void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) {
__ Addu(t2, t2, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(t2);
__ bind(&set_global_proxy);
__ LoadGlobalProxy(t0);
__ sw(t0, MemOperand(t8));
__ Branch(&valid_receiver);
// Compatible receiver check failed: throw an Illegal Invocation exception.
__ bind(&receiver_check_failed);
// Drop the arguments (including the receiver);
......
......@@ -1217,10 +1217,6 @@ static void CompatibleReceiverCheck(MacroAssembler* masm, Register receiver,
Register constructor = a4;
Register scratch = a5;
// If the receiver is not an object, jump to receiver_check_failed.
__ GetObjectType(receiver, map, scratch);
__ Branch(receiver_check_failed, lo, scratch, Operand(FIRST_JS_OBJECT_TYPE));
// If there is no signature, return the holder.
__ ld(signature, FieldMemOperand(function_template_info,
FunctionTemplateInfo::kSignatureOffset));
......@@ -1287,22 +1283,15 @@ void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) {
// -- sp[8 * argc] : receiver
// -----------------------------------
// Load the receiver.
__ sll(at, a0, kPointerSizeLog2);
__ Daddu(t8, sp, at);
__ ld(t0, MemOperand(t8));
// Update the receiver if this is a contextual call.
Label set_global_proxy, valid_receiver;
__ JumpIfRoot(t0, Heap::kUndefinedValueRootIndex, &set_global_proxy);
// Load the FunctionTemplateInfo.
__ ld(t1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ bind(&valid_receiver);
__ ld(t1, FieldMemOperand(t1, SharedFunctionInfo::kFunctionDataOffset));
// Do the compatible receiver check
Label receiver_check_failed;
__ sll(at, a0, kPointerSizeLog2);
__ Daddu(t8, sp, at);
__ ld(t0, MemOperand(t8));
CompatibleReceiverCheck(masm, t0, t1, &receiver_check_failed);
// Get the callback offset from the FunctionTemplateInfo, and jump to the
......@@ -1312,11 +1301,6 @@ void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) {
__ Daddu(t2, t2, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(t2);
__ bind(&set_global_proxy);
__ LoadGlobalProxy(t0);
__ sd(t0, MemOperand(t8));
__ Branch(&valid_receiver);
// Compatible receiver check failed: throw an Illegal Invocation exception.
__ bind(&receiver_check_failed);
// Drop the arguments (including the receiver);
......
......@@ -2332,10 +2332,6 @@ static void CompatibleReceiverCheck(MacroAssembler* masm, Register receiver,
Register map = scratch1;
Register constructor = scratch2;
// If the receiver is not an object, jump to receiver_check_failed.
__ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, kScratchRegister);
__ j(below, receiver_check_failed);
// If there is no signature, return the holder.
__ movp(signature, FieldOperand(function_template_info,
FunctionTemplateInfo::kSignatureOffset));
......@@ -2408,13 +2404,6 @@ void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) {
// -----------------------------------
StackArgumentsAccessor args(rsp, rax);
__ movp(rcx, args.GetReceiverOperand());
// Update the receiver if this is a contextual call.
Label set_global_proxy, valid_receiver;
__ CompareRoot(rcx, Heap::kUndefinedValueRootIndex);
__ j(equal, &set_global_proxy);
__ bind(&valid_receiver);
// Load the FunctionTemplateInfo.
__ movp(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
......@@ -2422,6 +2411,7 @@ void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) {
// Do the compatible receiver check.
Label receiver_check_failed;
__ movp(rcx, args.GetReceiverOperand());
CompatibleReceiverCheck(masm, rcx, rbx, rdx, r8, r9, &receiver_check_failed);
// Get the callback offset from the FunctionTemplateInfo, and jump to the
......@@ -2431,12 +2421,6 @@ void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) {
__ addp(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ jmp(rdx);
__ bind(&set_global_proxy);
__ movp(rcx, NativeContextOperand());
__ movp(rcx, ContextOperand(rcx, Context::GLOBAL_PROXY_INDEX));
__ movp(args.GetReceiverOperand(), rcx);
__ jmp(&valid_receiver, Label::kNear);
// Compatible receiver check failed: pop return address, arguments and
// receiver and throw an Illegal Invocation exception.
__ bind(&receiver_check_failed);
......
......@@ -22172,6 +22172,12 @@ TEST(EmptyApiCallback) {
result = CompileRun("x(1,2,3)");
CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
result = CompileRun("x.call(undefined)");
CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
result = CompileRun("x.call(null)");
CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
result = CompileRun("7 + x.call(3) + 11");
CHECK(result->IsInt32());
CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
......
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