summaryrefslogtreecommitdiff
path: root/chromium
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-01-15 10:25:41 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-01-15 12:31:26 +0000
commit4848d71bd91915a856f17a2bc45b402bda1d96f7 (patch)
tree6156ea01655bc723ce5db7c3e0f357953ae8a340 /chromium
parent35e15c600128669499d1a6994886050bab51d646 (diff)
downloadqtwebengine-chromium-4848d71bd91915a856f17a2bc45b402bda1d96f7.tar.gz
[Backport] Security bug 881252 and 896326
Check for stack overflow when pushing arguments in JSConstructStubGeneric Bug: chromium:896326 Change-Id: I9257573963f611711edbc48a46a3bacbe12a567d Reviewed-on: https://chromium-review.googlesource.com/c/1305934 Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Commit-Queue: Mythri Alle <mythria@chromium.org> Cr-Commit-Position: refs/heads/master@{#57398} Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium')
-rw-r--r--chromium/v8/src/builtins/arm/builtins-arm.cc42
-rw-r--r--chromium/v8/src/builtins/arm64/builtins-arm64.cc69
-rw-r--r--chromium/v8/src/builtins/ia32/builtins-ia32.cc65
-rw-r--r--chromium/v8/src/builtins/x64/builtins-x64.cc54
4 files changed, 152 insertions, 78 deletions
diff --git a/chromium/v8/src/builtins/arm/builtins-arm.cc b/chromium/v8/src/builtins/arm/builtins-arm.cc
index a5219bf0701..e30100452b8 100644
--- a/chromium/v8/src/builtins/arm/builtins-arm.cc
+++ b/chromium/v8/src/builtins/arm/builtins-arm.cc
@@ -167,6 +167,20 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
__ 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, Heap::kRealStackLimitRootIndex);
+ // 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.
+}
+
} // namespace
// The construct stub for ES5 constructor functions and ES6 class constructors.
@@ -251,6 +265,19 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// Set up pointer to last argument.
__ add(r4, fp, Operand(StandardFrameConstants::kCallerSPOffset));
+ Label enough_stack_space, stack_overflow;
+ Generate_StackOverflowCheck(masm, r0, r5, &stack_overflow);
+ __ b(&enough_stack_space);
+
+ __ bind(&stack_overflow);
+ // Restore the context from the frame.
+ __ ldr(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
+ __ CallRuntime(Runtime::kThrowStackOverflow);
+ // Unreachable code.
+ __ bkpt(0);
+
+ __ bind(&enough_stack_space);
+
// Copy arguments and receiver to the expression stack.
Label loop, entry;
__ mov(r5, r0);
@@ -495,21 +522,6 @@ void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
__ CallRuntime(Runtime::kThrowConstructedNonConstructable);
}
-static 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, Heap::kRealStackLimitRootIndex);
- // 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.
-}
-
static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
bool is_construct) {
// Called from Generate_JS_Entry
diff --git a/chromium/v8/src/builtins/arm64/builtins-arm64.cc b/chromium/v8/src/builtins/arm64/builtins-arm64.cc
index 2254f010c13..6bad8b2849c 100644
--- a/chromium/v8/src/builtins/arm64/builtins-arm64.cc
+++ b/chromium/v8/src/builtins/arm64/builtins-arm64.cc
@@ -193,6 +193,44 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
__ 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.
+ Label enough_stack_space;
+ __ LoadRoot(scratch, Heap::kRealStackLimitRootIndex);
+ // 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);
+
+#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, kPointerSizeLog2));
+ __ 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
+}
+
} // namespace
// The construct stub for ES5 constructor functions and ES6 class constructors.
@@ -301,6 +339,19 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// slots for the arguments. If the number of arguments was odd, the last
// argument will overwrite one of the receivers pushed above.
__ Bic(x10, x12, 1);
+
+ // Check if we have enough stack space to push all arguments.
+ Label enough_stack_space, stack_overflow;
+ Generate_StackOverflowCheck(masm, x10, &stack_overflow);
+ __ B(&enough_stack_space);
+
+ __ Bind(&stack_overflow);
+ // Restore the context from the frame.
+ __ Ldr(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
+ __ CallRuntime(Runtime::kThrowStackOverflow);
+ __ Unreachable();
+
+ __ Bind(&enough_stack_space);
__ Claim(x10);
// Copy the arguments.
@@ -532,24 +583,6 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
}
}
-static 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.
- Label enough_stack_space;
- __ LoadRoot(scratch, Heap::kRealStackLimitRootIndex);
- // 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);
-}
-
// Input:
// x0: new.target.
// x1: function.
diff --git a/chromium/v8/src/builtins/ia32/builtins-ia32.cc b/chromium/v8/src/builtins/ia32/builtins-ia32.cc
index d1c0a5d5fbb..550342086a0 100644
--- a/chromium/v8/src/builtins/ia32/builtins-ia32.cc
+++ b/chromium/v8/src/builtins/ia32/builtins-ia32.cc
@@ -133,6 +133,30 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
__ 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(kPointerSize == 4,
+ "The next instruction assumes kPointerSize == 4");
+ __ lea(scratch, Operand(scratch, num_args, times_4, 0));
+ if (include_receiver) {
+ __ add(scratch, Immediate(kPointerSize));
+ }
+ // See if we overflowed, i.e. scratch is positive.
+ __ cmp(scratch, Immediate(0));
+ __ j(greater, stack_overflow); // Signed comparison.
+}
+
} // namespace
// The construct stub for ES5 constructor functions and ES6 class constructors.
@@ -222,6 +246,21 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// Set up pointer to last argument.
__ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset));
+ // Check if we have enough stack space to push all arguments.
+ // Argument count in eax. Clobbers ecx.
+ Label enough_stack_space, stack_overflow;
+ Generate_StackOverflowCheck(masm, eax, ecx, &stack_overflow);
+ __ jmp(&enough_stack_space);
+
+ __ bind(&stack_overflow);
+ // Restore context from the frame.
+ __ mov(esi, Operand(ebp, ConstructFrameConstants::kContextOffset));
+ __ CallRuntime(Runtime::kThrowStackOverflow);
+ // This should be unreachable.
+ __ int3();
+
+ __ bind(&enough_stack_space);
+
// Copy arguments and receiver to the expression stack.
Label loop, entry;
__ mov(ecx, eax);
@@ -318,32 +357,6 @@ void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
__ CallRuntime(Runtime::kThrowConstructedNonConstructable);
}
-static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
- Register scratch1, Register scratch2,
- 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());
- __ mov(scratch1, Operand::StaticVariable(real_stack_limit));
- // Make scratch2 the space we have left. The stack might already be overflowed
- // here which will cause scratch2 to become negative.
- __ mov(scratch2, esp);
- __ sub(scratch2, scratch1);
- // Make scratch1 the space we need for the array when it is unrolled onto the
- // stack.
- __ mov(scratch1, num_args);
- if (include_receiver) {
- __ add(scratch1, Immediate(1));
- }
- __ shl(scratch1, kPointerSizeLog2);
- // Check if the arguments will overflow the stack.
- __ cmp(scratch2, scratch1);
- __ j(less_equal, stack_overflow); // Signed comparison.
-}
-
static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
bool is_construct) {
ProfileEntryHookStub::MaybeCallEntryHook(masm);
diff --git a/chromium/v8/src/builtins/x64/builtins-x64.cc b/chromium/v8/src/builtins/x64/builtins-x64.cc
index 438b577af6b..1c7413722b7 100644
--- a/chromium/v8/src/builtins/x64/builtins-x64.cc
+++ b/chromium/v8/src/builtins/x64/builtins-x64.cc
@@ -133,6 +133,26 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
__ 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, Heap::kRealStackLimitRootIndex);
+ __ movp(scratch, rsp);
+ // Make scratch the space we have left. The stack might already be overflowed
+ // here which will cause scratch to become negative.
+ __ subp(scratch, kScratchRegister);
+ __ sarp(scratch, Immediate(kPointerSizeLog2));
+ // Check if the arguments will overflow the stack.
+ __ cmpp(scratch, num_args);
+ // Signed comparison.
+ __ j(less_equal, stack_overflow, stack_overflow_distance);
+}
+
} // namespace
// The construct stub for ES5 constructor functions and ES6 class constructors.
@@ -219,6 +239,21 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// Set up pointer to last argument.
__ leap(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset));
+ // Check if we have enough stack space to push all arguments.
+ // Argument count in rax. Clobbers rcx.
+ Label enough_stack_space, stack_overflow;
+ Generate_StackOverflowCheck(masm, rax, rcx, &stack_overflow, Label::kNear);
+ __ jmp(&enough_stack_space, Label::kNear);
+
+ __ bind(&stack_overflow);
+ // Restore context from the frame.
+ __ movp(rsi, Operand(rbp, ConstructFrameConstants::kContextOffset));
+ __ CallRuntime(Runtime::kThrowStackOverflow);
+ // This should be unreachable.
+ __ int3();
+
+ __ bind(&enough_stack_space);
+
// Copy arguments and receiver to the expression stack.
Label loop, entry;
__ movp(rcx, rax);
@@ -315,25 +350,6 @@ void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
__ CallRuntime(Runtime::kThrowConstructedNonConstructable);
}
-static 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, Heap::kRealStackLimitRootIndex);
- __ movp(scratch, rsp);
- // Make scratch the space we have left. The stack might already be overflowed
- // here which will cause scratch to become negative.
- __ subp(scratch, kScratchRegister);
- __ sarp(scratch, Immediate(kPointerSizeLog2));
- // Check if the arguments will overflow the stack.
- __ cmpp(scratch, num_args);
- // Signed comparison.
- __ j(less_equal, stack_overflow, stack_overflow_distance);
-}
-
static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
bool is_construct) {
ProfileEntryHookStub::MaybeCallEntryHook(masm);