Skip to content

Commit

Permalink
Merged: [builtins] Check for stack overflow in JSConstructStub
Browse files Browse the repository at this point in the history
Revision: 0a0d70eb8c8652c415b78feb7d8c96f9760673f0

BUG=chromium:951322
LOG=N
NOTRY=true
NOPRESUBMIT=true
NOTREECHECKS=true
R=neis@chromium.org

Change-Id: If5e47223e38ae0c106932f6eca6529ae18b40c80
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1593298
Reviewed-by: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/branch-heads/7.5@{#16}
Cr-Branched-From: 35b9bf5-refs/heads/7.5.288@{#1}
Cr-Branched-From: 912b391-refs/heads/master@{#60911}
  • Loading branch information
sigurdschneider committed May 2, 2019
1 parent 80a924d commit 72b766d
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 90 deletions.
37 changes: 24 additions & 13 deletions src/builtins/arm/builtins-arm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,20 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm,

namespace {

void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
Register scratch, Label* stack_overflow) {
// Check the stack for overflow. We are not trying to catch
// interruptions (e.g. debug break and preemption) here, so the "real stack
// limit" is checked.
__ LoadRoot(scratch, RootIndex::kRealStackLimit);
// Make scratch the space we have left. The stack might already be overflowed
// here which will cause scratch to become negative.
__ sub(scratch, sp, scratch);
// Check if the arguments will overflow the stack.
__ cmp(scratch, Operand(num_args, LSL, kPointerSizeLog2));
__ b(le, stack_overflow); // Signed comparison.
}

void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : number of arguments
Expand All @@ -109,6 +123,10 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {

Register scratch = r2;

Label stack_overflow;

Generate_StackOverflowCheck(masm, r0, scratch, &stack_overflow);

// Enter a construct frame.
{
FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT);
Expand Down Expand Up @@ -164,20 +182,13 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
__ add(sp, sp, Operand(scratch, LSL, kPointerSizeLog2 - kSmiTagSize));
__ add(sp, sp, Operand(kPointerSize));
__ Jump(lr);
}

void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
Register scratch, Label* stack_overflow) {
// Check the stack for overflow. We are not trying to catch
// interruptions (e.g. debug break and preemption) here, so the "real stack
// limit" is checked.
__ LoadRoot(scratch, RootIndex::kRealStackLimit);
// Make scratch the space we have left. The stack might already be overflowed
// here which will cause scratch to become negative.
__ sub(scratch, sp, scratch);
// Check if the arguments will overflow the stack.
__ cmp(scratch, Operand(num_args, LSL, kPointerSizeLog2));
__ b(le, stack_overflow); // Signed comparison.
__ bind(&stack_overflow);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ CallRuntime(Runtime::kThrowStackOverflow);
__ bkpt(0); // Unreachable code.
}
}

} // namespace
Expand Down
84 changes: 47 additions & 37 deletions src/builtins/arm64/builtins-arm64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,44 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm,

namespace {

void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
Label* stack_overflow) {
UseScratchRegisterScope temps(masm);
Register scratch = temps.AcquireX();

// Check the stack for overflow.
// We are not trying to catch interruptions (e.g. debug break and
// preemption) here, so the "real stack limit" is checked.

__ LoadRoot(scratch, RootIndex::kRealStackLimit);
// Make scratch the space we have left. The stack might already be overflowed
// here which will cause scratch to become negative.
__ Sub(scratch, sp, scratch);
// Check if the arguments will overflow the stack.
__ Cmp(scratch, Operand(num_args, LSL, kSystemPointerSizeLog2));
__ B(le, stack_overflow);

#if defined(V8_OS_WIN)
// Simulate _chkstk to extend stack guard page on Windows ARM64.
const int kPageSize = 4096;
Label chkstk, chkstk_done;
Register probe = temps.AcquireX();

__ Sub(scratch, sp, Operand(num_args, LSL, kSystemPointerSizeLog2));
__ Mov(probe, sp);

// Loop start of stack probe.
__ Bind(&chkstk);
__ Sub(probe, probe, kPageSize);
__ Cmp(probe, scratch);
__ B(lo, &chkstk_done);
__ Ldrb(xzr, MemOperand(probe));
__ B(&chkstk);

__ Bind(&chkstk_done);
#endif
}

void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- x0 : number of arguments
Expand All @@ -103,6 +141,9 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// -----------------------------------

ASM_LOCATION("Builtins::Generate_JSConstructStubHelper");
Label stack_overflow;

Generate_StackOverflowCheck(masm, x0, &stack_overflow);

// Enter a construct frame.
{
Expand Down Expand Up @@ -193,44 +234,13 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// Remove caller arguments from the stack and return.
__ DropArguments(x1, TurboAssembler::kCountExcludesReceiver);
__ Ret();
}

void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
Label* stack_overflow) {
UseScratchRegisterScope temps(masm);
Register scratch = temps.AcquireX();

// Check the stack for overflow.
// We are not trying to catch interruptions (e.g. debug break and
// preemption) here, so the "real stack limit" is checked.

__ LoadRoot(scratch, RootIndex::kRealStackLimit);
// Make scratch the space we have left. The stack might already be overflowed
// here which will cause scratch to become negative.
__ Sub(scratch, sp, scratch);
// Check if the arguments will overflow the stack.
__ Cmp(scratch, Operand(num_args, LSL, kSystemPointerSizeLog2));
__ B(le, stack_overflow);

#if defined(V8_OS_WIN)
// Simulate _chkstk to extend stack guard page on Windows ARM64.
const int kPageSize = 4096;
Label chkstk, chkstk_done;
Register probe = temps.AcquireX();

__ Sub(scratch, sp, Operand(num_args, LSL, kSystemPointerSizeLog2));
__ Mov(probe, sp);

// Loop start of stack probe.
__ Bind(&chkstk);
__ Sub(probe, probe, kPageSize);
__ Cmp(probe, scratch);
__ B(lo, &chkstk_done);
__ Ldrb(xzr, MemOperand(probe));
__ B(&chkstk);

__ Bind(&chkstk_done);
#endif
__ Bind(&stack_overflow);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ CallRuntime(Runtime::kThrowStackOverflow);
__ Unreachable();
}
}

} // namespace
Expand Down
55 changes: 33 additions & 22 deletions src/builtins/ia32/builtins-ia32.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,30 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm,

namespace {

void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
Register scratch, Label* stack_overflow,
bool include_receiver = false) {
// Check the stack for overflow. We are not trying to catch
// interruptions (e.g. debug break and preemption) here, so the "real stack
// limit" is checked.
ExternalReference real_stack_limit =
ExternalReference::address_of_real_stack_limit(masm->isolate());
// Compute the space that is left as a negative number in scratch. If
// we already overflowed, this will be a positive number.
__ mov(scratch, __ ExternalReferenceAsOperand(real_stack_limit, scratch));
__ sub(scratch, esp);
// Add the size of the arguments.
static_assert(kSystemPointerSize == 4,
"The next instruction assumes kSystemPointerSize == 4");
__ lea(scratch, Operand(scratch, num_args, times_system_pointer_size, 0));
if (include_receiver) {
__ add(scratch, Immediate(kSystemPointerSize));
}
// See if we overflowed, i.e. scratch is positive.
__ cmp(scratch, Immediate(0));
__ j(greater, stack_overflow); // Signed comparison.
}

void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax: number of arguments
Expand All @@ -80,6 +104,10 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// -- esi: context
// -----------------------------------

Label stack_overflow;

Generate_StackOverflowCheck(masm, eax, ecx, &stack_overflow);

// Enter a construct frame.
{
FrameScope scope(masm, StackFrame::CONSTRUCT);
Expand Down Expand Up @@ -139,30 +167,13 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
1 * kSystemPointerSize)); // 1 ~ receiver
__ PushReturnAddressFrom(ecx);
__ ret(0);
}

void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
Register scratch, Label* stack_overflow,
bool include_receiver = false) {
// Check the stack for overflow. We are not trying to catch
// interruptions (e.g. debug break and preemption) here, so the "real stack
// limit" is checked.
ExternalReference real_stack_limit =
ExternalReference::address_of_real_stack_limit(masm->isolate());
// Compute the space that is left as a negative number in scratch. If
// we already overflowed, this will be a positive number.
__ mov(scratch, __ ExternalReferenceAsOperand(real_stack_limit, scratch));
__ sub(scratch, esp);
// Add the size of the arguments.
static_assert(kSystemPointerSize == 4,
"The next instruction assumes kSystemPointerSize == 4");
__ lea(scratch, Operand(scratch, num_args, times_system_pointer_size, 0));
if (include_receiver) {
__ add(scratch, Immediate(kSystemPointerSize));
__ bind(&stack_overflow);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ CallRuntime(Runtime::kThrowStackOverflow);
__ int3(); // This should be unreachable.
}
// See if we overflowed, i.e. scratch is positive.
__ cmp(scratch, Immediate(0));
__ j(greater, stack_overflow); // Signed comparison.
}

} // namespace
Expand Down
46 changes: 28 additions & 18 deletions src/builtins/x64/builtins-x64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,25 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm,

namespace {

void Generate_StackOverflowCheck(
MacroAssembler* masm, Register num_args, Register scratch,
Label* stack_overflow,
Label::Distance stack_overflow_distance = Label::kFar) {
// Check the stack for overflow. We are not trying to catch
// interruptions (e.g. debug break and preemption) here, so the "real stack
// limit" is checked.
__ LoadRoot(kScratchRegister, RootIndex::kRealStackLimit);
__ movq(scratch, rsp);
// Make scratch the space we have left. The stack might already be overflowed
// here which will cause scratch to become negative.
__ subq(scratch, kScratchRegister);
__ sarq(scratch, Immediate(kSystemPointerSizeLog2));
// Check if the arguments will overflow the stack.
__ cmpq(scratch, num_args);
// Signed comparison.
__ j(less_equal, stack_overflow, stack_overflow_distance);
}

void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax: number of arguments
Expand All @@ -79,6 +98,9 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// -- rsi: context
// -----------------------------------

Label stack_overflow;
Generate_StackOverflowCheck(masm, rax, rcx, &stack_overflow, Label::kFar);

// Enter a construct frame.
{
FrameScope scope(masm, StackFrame::CONSTRUCT);
Expand Down Expand Up @@ -136,25 +158,13 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
__ PushReturnAddressFrom(rcx);

__ ret(0);
}

void Generate_StackOverflowCheck(
MacroAssembler* masm, Register num_args, Register scratch,
Label* stack_overflow,
Label::Distance stack_overflow_distance = Label::kFar) {
// Check the stack for overflow. We are not trying to catch
// interruptions (e.g. debug break and preemption) here, so the "real stack
// limit" is checked.
__ LoadRoot(kScratchRegister, RootIndex::kRealStackLimit);
__ movq(scratch, rsp);
// Make scratch the space we have left. The stack might already be overflowed
// here which will cause scratch to become negative.
__ subq(scratch, kScratchRegister);
__ sarq(scratch, Immediate(kSystemPointerSizeLog2));
// Check if the arguments will overflow the stack.
__ cmpq(scratch, num_args);
// Signed comparison.
__ j(less_equal, stack_overflow, stack_overflow_distance);
__ bind(&stack_overflow);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ CallRuntime(Runtime::kThrowStackOverflow);
__ int3(); // This should be unreachable.
}
}

} // namespace
Expand Down

0 comments on commit 72b766d

Please sign in to comment.