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,
// -- r0 : the number of arguments
// -- r1 : the function to call (checked to be a JSFunction)
// -----------------------------------
__ AssertCallableFunction(r1);
__ AssertFunction(r1);
Label class_constructor;
__ 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
// context, and we also need to take the global proxy from the function
......@@ -2360,6 +2364,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ ldrh(r2,
FieldMemOperand(r2, SharedFunctionInfo::kFormalParameterCountOffset));
__ 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 {
......
......@@ -2655,10 +2655,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// -- x0 : the number of arguments
// -- x1 : the function to call (checked to be a JSFunction)
// -----------------------------------
__ AssertCallableFunction(x1);
__ AssertFunction(x1);
Label class_constructor;
__ LoadTaggedPointerField(
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
// context, and we also need to take the global proxy from the function
......@@ -2734,6 +2738,15 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ Ldrh(x2,
FieldMemOperand(x2, SharedFunctionInfo::kFormalParameterCountOffset));
__ 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 {
......
......@@ -2447,9 +2447,13 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// -- edi : the function to call (checked to be a JSFunction)
// -----------------------------------
StackArgumentsAccessor args(eax);
__ AssertCallableFunction(edi, edx);
__ AssertFunction(edi, edx);
Label class_constructor;
__ 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
// context, and we also need to take the global proxy from the function
......@@ -2530,6 +2534,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ movzx_w(
ecx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
__ 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 {
......
......@@ -2303,7 +2303,12 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// -----------------------------------
__ AssertFunction(a1);
Label class_constructor;
__ 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
// context, and we also need to take the global proxy from the function
......@@ -2379,6 +2384,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ Ld_hu(
a2, FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset));
__ 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
......
......@@ -2246,7 +2246,12 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// -----------------------------------
__ AssertFunction(a1);
Label class_constructor;
__ 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
// context, and we also need to take the global proxy from the function
......@@ -2322,6 +2327,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ lhu(a2,
FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset));
__ 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
......
......@@ -2299,7 +2299,12 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// -----------------------------------
__ AssertFunction(a1);
Label class_constructor;
__ 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
// context, and we also need to take the global proxy from the function
......@@ -2375,6 +2380,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ Lhu(a2,
FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset));
__ 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
......
......@@ -2117,10 +2117,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// -- r3 : the number of arguments
// -- r4 : the function to call (checked to be a JSFunction)
// -----------------------------------
__ AssertCallableFunction(r4);
__ AssertFunction(r4);
Label class_constructor;
__ LoadTaggedPointerField(
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
// context, and we also need to take the global proxy from the function
......@@ -2198,6 +2202,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ LoadU16(
r5, FieldMemOperand(r5, SharedFunctionInfo::kFormalParameterCountOffset));
__ 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 {
......
......@@ -2434,10 +2434,16 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// -- a0 : the number of arguments
// -- a1 : the function to call (checked to be a JSFunction)
// -----------------------------------
__ AssertCallableFunction(a1);
__ AssertFunction(a1);
Label class_constructor;
__ LoadTaggedPointerField(
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
// context, and we also need to take the global proxy from the function
// context in case of conversion.
......@@ -2515,6 +2521,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ Lhu(a2,
FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset));
__ 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 {
......
......@@ -2524,10 +2524,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// -- r2 : the number of arguments
// -- r3 : the function to call (checked to be a JSFunction)
// -----------------------------------
__ AssertCallableFunction(r3);
__ AssertFunction(r3);
Label class_constructor;
__ LoadTaggedPointerField(
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
// context, and we also need to take the global proxy from the function
......@@ -2605,6 +2609,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ LoadU16(
r4, FieldMemOperand(r4, SharedFunctionInfo::kFormalParameterCountOffset));
__ 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 {
......
......@@ -2377,10 +2377,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// -----------------------------------
StackArgumentsAccessor args(rax);
__ AssertCallableFunction(rdi);
__ AssertFunction(rdi);
Label class_constructor;
__ LoadTaggedPointerField(
rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
__ testl(FieldOperand(rdx, SharedFunctionInfo::kFlagsOffset),
Immediate(SharedFunctionInfo::IsClassConstructorBit::kMask));
__ j(not_zero, &class_constructor);
// ----------- S t a t e -------------
// -- rax : the number of arguments
// -- rdx : the shared function info.
......@@ -2465,6 +2469,14 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ movzxwq(
rbx, FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset));
__ 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 {
......
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