Commit 3e40f8f0 authored by Patrick Thier's avatar Patrick Thier Committed by V8 LUCI CQ

Add check for class constructor to CallFunction

Raise an exception if CallFunction is invoked with a class constructor.
The check was initially removed in [1] but there are cases where we
could end in CallFunction with class constructors from optimized code.

[1] https://crrev.com/c/3186434

Bug: chromium:1271384
Change-Id: I0d700c4b1d117334c1c4c14719e24cd1f2c5e3a2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3291313
Commit-Queue: Patrick Thier <pthier@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77967}
parent 622dc9b7
...@@ -2283,9 +2283,13 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2283,9 +2283,13 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// -- r0 : the number of arguments // -- r0 : the number of arguments
// -- r1 : the function to call (checked to be a JSFunction) // -- r1 : the function to call (checked to be a JSFunction)
// ----------------------------------- // -----------------------------------
__ AssertCallableFunction(r1); __ AssertFunction(r1);
Label class_constructor;
__ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
__ ldr(r3, FieldMemOperand(r2, SharedFunctionInfo::kFlagsOffset));
__ tst(r3, Operand(SharedFunctionInfo::IsClassConstructorBit::kMask));
__ b(ne, &class_constructor);
// Enter the context of the function; ToObject has to run in the function // Enter the context of the function; ToObject has to run in the function
// context, and we also need to take the global proxy from the function // context, and we also need to take the global proxy from the function
...@@ -2360,6 +2364,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2360,6 +2364,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ ldrh(r2, __ ldrh(r2,
FieldMemOperand(r2, SharedFunctionInfo::kFormalParameterCountOffset)); FieldMemOperand(r2, SharedFunctionInfo::kFormalParameterCountOffset));
__ InvokeFunctionCode(r1, no_reg, r2, r0, InvokeType::kJump); __ InvokeFunctionCode(r1, no_reg, r2, r0, InvokeType::kJump);
// The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ push(r1);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
}
} }
namespace { namespace {
......
...@@ -2655,10 +2655,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2655,10 +2655,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// -- x0 : the number of arguments // -- x0 : the number of arguments
// -- x1 : the function to call (checked to be a JSFunction) // -- x1 : the function to call (checked to be a JSFunction)
// ----------------------------------- // -----------------------------------
__ AssertCallableFunction(x1); __ AssertFunction(x1);
Label class_constructor;
__ LoadTaggedPointerField( __ LoadTaggedPointerField(
x2, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); x2, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
__ Ldr(w3, FieldMemOperand(x2, SharedFunctionInfo::kFlagsOffset));
__ TestAndBranchIfAnySet(w3, SharedFunctionInfo::IsClassConstructorBit::kMask,
&class_constructor);
// Enter the context of the function; ToObject has to run in the function // Enter the context of the function; ToObject has to run in the function
// context, and we also need to take the global proxy from the function // context, and we also need to take the global proxy from the function
...@@ -2734,6 +2738,15 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2734,6 +2738,15 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ Ldrh(x2, __ Ldrh(x2,
FieldMemOperand(x2, SharedFunctionInfo::kFormalParameterCountOffset)); FieldMemOperand(x2, SharedFunctionInfo::kFormalParameterCountOffset));
__ InvokeFunctionCode(x1, no_reg, x2, x0, InvokeType::kJump); __ InvokeFunctionCode(x1, no_reg, x2, x0, InvokeType::kJump);
// The function is a "classConstructor", need to raise an exception.
__ Bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ PushArgument(x1);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
__ Unreachable();
}
} }
namespace { namespace {
......
...@@ -2447,9 +2447,13 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2447,9 +2447,13 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// -- edi : the function to call (checked to be a JSFunction) // -- edi : the function to call (checked to be a JSFunction)
// ----------------------------------- // -----------------------------------
StackArgumentsAccessor args(eax); StackArgumentsAccessor args(eax);
__ AssertCallableFunction(edi, edx); __ AssertFunction(edi, edx);
Label class_constructor;
__ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
__ test(FieldOperand(edx, SharedFunctionInfo::kFlagsOffset),
Immediate(SharedFunctionInfo::IsClassConstructorBit::kMask));
__ j(not_zero, &class_constructor);
// Enter the context of the function; ToObject has to run in the function // Enter the context of the function; ToObject has to run in the function
// context, and we also need to take the global proxy from the function // context, and we also need to take the global proxy from the function
...@@ -2530,6 +2534,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2530,6 +2534,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ movzx_w( __ movzx_w(
ecx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); ecx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
__ InvokeFunctionCode(edi, no_reg, ecx, eax, InvokeType::kJump); __ InvokeFunctionCode(edi, no_reg, ecx, eax, InvokeType::kJump);
// The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ push(edi);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
}
} }
namespace { namespace {
......
...@@ -2303,7 +2303,12 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2303,7 +2303,12 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// ----------------------------------- // -----------------------------------
__ AssertFunction(a1); __ AssertFunction(a1);
Label class_constructor;
__ Ld_d(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); __ Ld_d(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ Ld_wu(a3, FieldMemOperand(a2, SharedFunctionInfo::kFlagsOffset));
__ And(kScratchReg, a3,
Operand(SharedFunctionInfo::IsClassConstructorBit::kMask));
__ Branch(&class_constructor, ne, kScratchReg, Operand(zero_reg));
// Enter the context of the function; ToObject has to run in the function // Enter the context of the function; ToObject has to run in the function
// context, and we also need to take the global proxy from the function // context, and we also need to take the global proxy from the function
...@@ -2379,6 +2384,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2379,6 +2384,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ Ld_hu( __ Ld_hu(
a2, FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset)); a2, FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset));
__ InvokeFunctionCode(a1, no_reg, a2, a0, InvokeType::kJump); __ InvokeFunctionCode(a1, no_reg, a2, a0, InvokeType::kJump);
// The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ Push(a1);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
}
} }
// static // static
......
...@@ -2246,7 +2246,12 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2246,7 +2246,12 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// ----------------------------------- // -----------------------------------
__ AssertFunction(a1); __ AssertFunction(a1);
Label class_constructor;
__ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ lw(a3, FieldMemOperand(a2, SharedFunctionInfo::kFlagsOffset));
__ And(kScratchReg, a3,
Operand(SharedFunctionInfo::IsClassConstructorBit::kMask));
__ Branch(&class_constructor, ne, kScratchReg, Operand(zero_reg));
// Enter the context of the function; ToObject has to run in the function // Enter the context of the function; ToObject has to run in the function
// context, and we also need to take the global proxy from the function // context, and we also need to take the global proxy from the function
...@@ -2322,6 +2327,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2322,6 +2327,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ lhu(a2, __ lhu(a2,
FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset)); FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset));
__ InvokeFunctionCode(a1, no_reg, a2, a0, InvokeType::kJump); __ InvokeFunctionCode(a1, no_reg, a2, a0, InvokeType::kJump);
// The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ Push(a1);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
}
} }
// static // static
......
...@@ -2299,7 +2299,12 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2299,7 +2299,12 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// ----------------------------------- // -----------------------------------
__ AssertFunction(a1); __ AssertFunction(a1);
Label class_constructor;
__ Ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); __ Ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ Lwu(a3, FieldMemOperand(a2, SharedFunctionInfo::kFlagsOffset));
__ And(kScratchReg, a3,
Operand(SharedFunctionInfo::IsClassConstructorBit::kMask));
__ Branch(&class_constructor, ne, kScratchReg, Operand(zero_reg));
// Enter the context of the function; ToObject has to run in the function // Enter the context of the function; ToObject has to run in the function
// context, and we also need to take the global proxy from the function // context, and we also need to take the global proxy from the function
...@@ -2375,6 +2380,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2375,6 +2380,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ Lhu(a2, __ Lhu(a2,
FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset)); FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset));
__ InvokeFunctionCode(a1, no_reg, a2, a0, InvokeType::kJump); __ InvokeFunctionCode(a1, no_reg, a2, a0, InvokeType::kJump);
// The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ Push(a1);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
}
} }
// static // static
......
...@@ -2117,10 +2117,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2117,10 +2117,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// -- r3 : the number of arguments // -- r3 : the number of arguments
// -- r4 : the function to call (checked to be a JSFunction) // -- r4 : the function to call (checked to be a JSFunction)
// ----------------------------------- // -----------------------------------
__ AssertCallableFunction(r4); __ AssertFunction(r4);
Label class_constructor;
__ LoadTaggedPointerField( __ LoadTaggedPointerField(
r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset), r0); r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset), r0);
__ lwz(r6, FieldMemOperand(r5, SharedFunctionInfo::kFlagsOffset));
__ TestBitMask(r6, SharedFunctionInfo::IsClassConstructorBit::kMask, r0);
__ bne(&class_constructor, cr0);
// Enter the context of the function; ToObject has to run in the function // Enter the context of the function; ToObject has to run in the function
// context, and we also need to take the global proxy from the function // context, and we also need to take the global proxy from the function
...@@ -2198,6 +2202,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2198,6 +2202,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ LoadU16( __ LoadU16(
r5, FieldMemOperand(r5, SharedFunctionInfo::kFormalParameterCountOffset)); r5, FieldMemOperand(r5, SharedFunctionInfo::kFormalParameterCountOffset));
__ InvokeFunctionCode(r4, no_reg, r5, r3, InvokeType::kJump); __ InvokeFunctionCode(r4, no_reg, r5, r3, InvokeType::kJump);
// The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor);
{
FrameAndConstantPoolScope frame(masm, StackFrame::INTERNAL);
__ push(r4);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
}
} }
namespace { namespace {
......
...@@ -2434,10 +2434,16 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2434,10 +2434,16 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// -- a0 : the number of arguments // -- a0 : the number of arguments
// -- a1 : the function to call (checked to be a JSFunction) // -- a1 : the function to call (checked to be a JSFunction)
// ----------------------------------- // -----------------------------------
__ AssertCallableFunction(a1); __ AssertFunction(a1);
Label class_constructor;
__ LoadTaggedPointerField( __ LoadTaggedPointerField(
a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ Lwu(a3, FieldMemOperand(a2, SharedFunctionInfo::kFlagsOffset));
__ And(kScratchReg, a3,
Operand(SharedFunctionInfo::IsClassConstructorBit::kMask));
__ Branch(&class_constructor, ne, kScratchReg, Operand(zero_reg));
// Enter the context of the function; ToObject has to run in the function // Enter the context of the function; ToObject has to run in the function
// context, and we also need to take the global proxy from the function // context, and we also need to take the global proxy from the function
// context in case of conversion. // context in case of conversion.
...@@ -2515,6 +2521,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2515,6 +2521,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ Lhu(a2, __ Lhu(a2,
FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset)); FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset));
__ InvokeFunctionCode(a1, no_reg, a2, a0, InvokeType::kJump); __ InvokeFunctionCode(a1, no_reg, a2, a0, InvokeType::kJump);
// The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ Push(a1);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
}
} }
namespace { namespace {
......
...@@ -2524,10 +2524,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2524,10 +2524,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// -- r2 : the number of arguments // -- r2 : the number of arguments
// -- r3 : the function to call (checked to be a JSFunction) // -- r3 : the function to call (checked to be a JSFunction)
// ----------------------------------- // -----------------------------------
__ AssertCallableFunction(r3); __ AssertFunction(r3);
Label class_constructor;
__ LoadTaggedPointerField( __ LoadTaggedPointerField(
r4, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset)); r4, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
__ LoadU32(r5, FieldMemOperand(r4, SharedFunctionInfo::kFlagsOffset));
__ TestBitMask(r5, SharedFunctionInfo::IsClassConstructorBit::kMask, r0);
__ bne(&class_constructor);
// Enter the context of the function; ToObject has to run in the function // Enter the context of the function; ToObject has to run in the function
// context, and we also need to take the global proxy from the function // context, and we also need to take the global proxy from the function
...@@ -2605,6 +2609,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2605,6 +2609,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ LoadU16( __ LoadU16(
r4, FieldMemOperand(r4, SharedFunctionInfo::kFormalParameterCountOffset)); r4, FieldMemOperand(r4, SharedFunctionInfo::kFormalParameterCountOffset));
__ InvokeFunctionCode(r3, no_reg, r4, r2, InvokeType::kJump); __ InvokeFunctionCode(r3, no_reg, r4, r2, InvokeType::kJump);
// The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor);
{
FrameAndConstantPoolScope frame(masm, StackFrame::INTERNAL);
__ push(r3);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
}
} }
namespace { namespace {
......
...@@ -2377,10 +2377,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2377,10 +2377,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// ----------------------------------- // -----------------------------------
StackArgumentsAccessor args(rax); StackArgumentsAccessor args(rax);
__ AssertCallableFunction(rdi); __ AssertFunction(rdi);
Label class_constructor;
__ LoadTaggedPointerField( __ LoadTaggedPointerField(
rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
__ testl(FieldOperand(rdx, SharedFunctionInfo::kFlagsOffset),
Immediate(SharedFunctionInfo::IsClassConstructorBit::kMask));
__ j(not_zero, &class_constructor);
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : the number of arguments // -- rax : the number of arguments
// -- rdx : the shared function info. // -- rdx : the shared function info.
...@@ -2465,6 +2469,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2465,6 +2469,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ movzxwq( __ movzxwq(
rbx, FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset)); rbx, FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset));
__ InvokeFunctionCode(rdi, no_reg, rbx, rax, InvokeType::kJump); __ InvokeFunctionCode(rdi, no_reg, rbx, rax, InvokeType::kJump);
// The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ Push(rdi);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
}
} }
namespace { namespace {
......
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