Commit bf782ec5 authored by petermarshall's avatar petermarshall Committed by Commit bot

[Builtins] Smi-check the spread and go to runtime in CheckSpreadAndPushToStack.

We did not smi-check the spread argument here, meaning we tried to take the map
of a smi, resulting in segfaults which clusterfuzz found.

Also added tests that exercise this path.

BUG=685086

Review-Url: https://codereview.chromium.org/2655013002
Cr-Commit-Position: refs/heads/master@{#42657}
parent 6053f4a3
...@@ -2632,10 +2632,11 @@ static void CheckSpreadAndPushToStack(MacroAssembler* masm) { ...@@ -2632,10 +2632,11 @@ static void CheckSpreadAndPushToStack(MacroAssembler* masm) {
Register spread_len = r5; Register spread_len = r5;
Label runtime_call, push_args;
__ ldr(spread, MemOperand(sp, 0)); __ ldr(spread, MemOperand(sp, 0));
__ JumpIfSmi(spread, &runtime_call);
__ ldr(spread_map, FieldMemOperand(spread, HeapObject::kMapOffset)); __ ldr(spread_map, FieldMemOperand(spread, HeapObject::kMapOffset));
Label runtime_call, push_args;
// Check that the spread is an array. // Check that the spread is an array.
__ CompareInstanceType(spread_map, scratch, JS_ARRAY_TYPE); __ CompareInstanceType(spread_map, scratch, JS_ARRAY_TYPE);
__ b(ne, &runtime_call); __ b(ne, &runtime_call);
......
...@@ -2711,10 +2711,11 @@ static void CheckSpreadAndPushToStack(MacroAssembler* masm) { ...@@ -2711,10 +2711,11 @@ static void CheckSpreadAndPushToStack(MacroAssembler* masm) {
Register spread_len = x5; Register spread_len = x5;
Label runtime_call, push_args;
__ Peek(spread, 0); __ Peek(spread, 0);
__ JumpIfSmi(spread, &runtime_call);
__ Ldr(spread_map, FieldMemOperand(spread, HeapObject::kMapOffset)); __ Ldr(spread_map, FieldMemOperand(spread, HeapObject::kMapOffset));
Label runtime_call, push_args;
// Check that the spread is an array. // Check that the spread is an array.
__ CompareInstanceType(spread_map, scratch, JS_ARRAY_TYPE); __ CompareInstanceType(spread_map, scratch, JS_ARRAY_TYPE);
__ B(ne, &runtime_call); __ B(ne, &runtime_call);
......
...@@ -2690,10 +2690,11 @@ static void CheckSpreadAndPushToStack(MacroAssembler* masm) { ...@@ -2690,10 +2690,11 @@ static void CheckSpreadAndPushToStack(MacroAssembler* masm) {
Register spread_len = edx; Register spread_len = edx;
Label runtime_call, push_args;
__ mov(spread, Operand(esp, kPointerSize)); __ mov(spread, Operand(esp, kPointerSize));
__ JumpIfSmi(spread, &runtime_call);
__ mov(spread_map, FieldOperand(spread, HeapObject::kMapOffset)); __ mov(spread_map, FieldOperand(spread, HeapObject::kMapOffset));
Label runtime_call, push_args;
// Check that the spread is an array. // Check that the spread is an array.
__ CmpInstanceType(spread_map, JS_ARRAY_TYPE); __ CmpInstanceType(spread_map, JS_ARRAY_TYPE);
__ j(not_equal, &runtime_call); __ j(not_equal, &runtime_call);
......
...@@ -2643,11 +2643,12 @@ static void CheckSpreadAndPushToStack(MacroAssembler* masm) { ...@@ -2643,11 +2643,12 @@ static void CheckSpreadAndPushToStack(MacroAssembler* masm) {
Register native_context = t4; Register native_context = t4;
Label runtime_call, push_args;
__ lw(spread, MemOperand(sp, 0)); __ lw(spread, MemOperand(sp, 0));
__ JumpIfSmi(spread, &runtime_call);
__ lw(spread_map, FieldMemOperand(spread, HeapObject::kMapOffset)); __ lw(spread_map, FieldMemOperand(spread, HeapObject::kMapOffset));
__ lw(native_context, NativeContextMemOperand()); __ lw(native_context, NativeContextMemOperand());
Label runtime_call, push_args;
// Check that the spread is an array. // Check that the spread is an array.
__ lbu(scratch, FieldMemOperand(spread_map, Map::kInstanceTypeOffset)); __ lbu(scratch, FieldMemOperand(spread_map, Map::kInstanceTypeOffset));
__ Branch(&runtime_call, ne, scratch, Operand(JS_ARRAY_TYPE)); __ Branch(&runtime_call, ne, scratch, Operand(JS_ARRAY_TYPE));
......
...@@ -2669,11 +2669,12 @@ static void CheckSpreadAndPushToStack(MacroAssembler* masm) { ...@@ -2669,11 +2669,12 @@ static void CheckSpreadAndPushToStack(MacroAssembler* masm) {
Register native_context = a5; Register native_context = a5;
Label runtime_call, push_args;
__ ld(spread, MemOperand(sp, 0)); __ ld(spread, MemOperand(sp, 0));
__ JumpIfSmi(spread, &runtime_call);
__ ld(spread_map, FieldMemOperand(spread, HeapObject::kMapOffset)); __ ld(spread_map, FieldMemOperand(spread, HeapObject::kMapOffset));
__ ld(native_context, NativeContextMemOperand()); __ ld(native_context, NativeContextMemOperand());
Label runtime_call, push_args;
// Check that the spread is an array. // Check that the spread is an array.
__ lbu(scratch, FieldMemOperand(spread_map, Map::kInstanceTypeOffset)); __ lbu(scratch, FieldMemOperand(spread_map, Map::kInstanceTypeOffset));
__ Branch(&runtime_call, ne, scratch, Operand(JS_ARRAY_TYPE)); __ Branch(&runtime_call, ne, scratch, Operand(JS_ARRAY_TYPE));
......
...@@ -2764,14 +2764,15 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode, ...@@ -2764,14 +2764,15 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode,
} }
static void CheckSpreadAndPushToStack(MacroAssembler* masm) { static void CheckSpreadAndPushToStack(MacroAssembler* masm) {
Label runtime_call, push_args;
// Load the spread argument into rbx. // Load the spread argument into rbx.
__ movp(rbx, Operand(rsp, kPointerSize)); __ movp(rbx, Operand(rsp, kPointerSize));
__ JumpIfSmi(rbx, &runtime_call);
// Load the map of the spread into r15. // Load the map of the spread into r15.
__ movp(r15, FieldOperand(rbx, HeapObject::kMapOffset)); __ movp(r15, FieldOperand(rbx, HeapObject::kMapOffset));
// Load native context into r14. // Load native context into r14.
__ movp(r14, NativeContextOperand()); __ movp(r14, NativeContextOperand());
Label runtime_call, push_args;
// Check that the spread is an array. // Check that the spread is an array.
__ CmpInstanceType(r15, JS_ARRAY_TYPE); __ CmpInstanceType(r15, JS_ARRAY_TYPE);
__ j(not_equal, &runtime_call); __ j(not_equal, &runtime_call);
......
...@@ -2722,10 +2722,11 @@ static void CheckSpreadAndPushToStack(MacroAssembler* masm) { ...@@ -2722,10 +2722,11 @@ static void CheckSpreadAndPushToStack(MacroAssembler* masm) {
Register spread_len = edx; Register spread_len = edx;
Label runtime_call, push_args;
__ mov(spread, Operand(esp, kPointerSize)); __ mov(spread, Operand(esp, kPointerSize));
__ JumpIfSmi(spread, &runtime_call);
__ mov(spread_map, FieldOperand(spread, HeapObject::kMapOffset)); __ mov(spread_map, FieldOperand(spread, HeapObject::kMapOffset));
Label runtime_call, push_args;
// Check that the spread is an array. // Check that the spread is an array.
__ CmpInstanceType(spread_map, JS_ARRAY_TYPE); __ CmpInstanceType(spread_map, JS_ARRAY_TYPE);
__ j(not_equal, &runtime_call); __ j(not_equal, &runtime_call);
......
...@@ -49,6 +49,9 @@ ...@@ -49,6 +49,9 @@
return sum; return sum;
} }
assertThrows(function() {
sum(...0);
}, TypeError);
assertEquals(void 0, sum(..."")); assertEquals(void 0, sum(...""));
assertEquals(void 0, sum(...[])); assertEquals(void 0, sum(...[]));
assertEquals(void 0, sum(...new Set)); assertEquals(void 0, sum(...new Set));
...@@ -201,6 +204,9 @@ ...@@ -201,6 +204,9 @@
return sum; return sum;
} }
assertThrows(function() {
sum(...0);
}, TypeError);
assertEquals(void 0, sum(..."")); assertEquals(void 0, sum(...""));
assertEquals(void 0, sum(...[])); assertEquals(void 0, sum(...[]));
assertEquals(void 0, sum(...new Set)); assertEquals(void 0, sum(...new Set));
......
// Copyright 2017 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.
try {
Math.max(...0);
} catch (e) {
}
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