Commit dcfc453e authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[csa] check arity when calling

Add information to CallInterfaceDescriptor if additional implicit arguments
can be passed on the stack, that is, if it is a varargs calling convention.

With this information, we can have a proper DCHECK in CSA to avoid passing
the wrong number of arguments to builtins that don't support it.
Previously, this lead to difficult to investigate crashes with misaligned
stacks.

Drive-by cleanup: Reduce duplication between DEFINE_PARAMETERS_... macros.

Change-Id: I449af6713a3cdd72e098d3481dfee62e01343f14
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1888932Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64666}
parent dba86292
...@@ -103,11 +103,14 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptorData { ...@@ -103,11 +103,14 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptorData {
enum Flag { enum Flag {
kNoFlags = 0u, kNoFlags = 0u,
kNoContext = 1u << 0, kNoContext = 1u << 0,
// This indicates that the code uses a special frame that does not scan the // This indicates that the code uses a special frame that does not scan the
// stack arguments, e.g. EntryFrame. And this allows the code to use // stack arguments, e.g. EntryFrame. And this allows the code to use
// untagged stack arguments. // untagged stack arguments.
kNoStackScan = 1u << 1, kNoStackScan = 1u << 1,
// In addition to the specified parameters, additional arguments can be
// passed on the stack.
// This does not indicate if arguments adaption is used or not.
kAllowVarArgs = 1u << 2,
}; };
using Flags = base::Flags<Flag>; using Flags = base::Flags<Flag>;
...@@ -249,6 +252,10 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptor { ...@@ -249,6 +252,10 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptor {
return (flags() & CallInterfaceDescriptorData::kNoContext) == 0; return (flags() & CallInterfaceDescriptorData::kNoContext) == 0;
} }
bool AllowVarArgs() const {
return flags() & CallInterfaceDescriptorData::kAllowVarArgs;
}
int GetReturnCount() const { return data()->return_count(); } int GetReturnCount() const { return data()->return_count(); }
MachineType GetReturnType(int index) const { MachineType GetReturnType(int index) const {
...@@ -400,9 +407,8 @@ STATIC_ASSERT(kMaxTFSBuiltinRegisterParams <= kMaxBuiltinRegisterParams); ...@@ -400,9 +407,8 @@ STATIC_ASSERT(kMaxTFSBuiltinRegisterParams <= kMaxBuiltinRegisterParams);
\ \
public: public:
#define DEFINE_RESULT_AND_PARAMETERS(return_count, ...) \ #define DEFINE_FLAGS_AND_RESULT_AND_PARAMETERS(flags, return_count, ...) \
static constexpr int kDescriptorFlags = \ static constexpr int kDescriptorFlags = flags; \
CallInterfaceDescriptorData::kNoFlags; \
static constexpr int kReturnCount = return_count; \ static constexpr int kReturnCount = return_count; \
enum ParameterIndices { \ enum ParameterIndices { \
__dummy = -1, /* to be able to pass zero arguments */ \ __dummy = -1, /* to be able to pass zero arguments */ \
...@@ -412,16 +418,9 @@ STATIC_ASSERT(kMaxTFSBuiltinRegisterParams <= kMaxBuiltinRegisterParams); ...@@ -412,16 +418,9 @@ STATIC_ASSERT(kMaxTFSBuiltinRegisterParams <= kMaxBuiltinRegisterParams);
kContext = kParameterCount /* implicit parameter */ \ kContext = kParameterCount /* implicit parameter */ \
}; };
#define DEFINE_RESULT_AND_PARAMETERS_NO_CONTEXT(return_count, ...) \ #define DEFINE_RESULT_AND_PARAMETERS(return_count, ...) \
static constexpr int kDescriptorFlags = \ DEFINE_FLAGS_AND_RESULT_AND_PARAMETERS( \
CallInterfaceDescriptorData::kNoContext; \ CallInterfaceDescriptorData::kNoFlags, return_count, ##__VA_ARGS__)
static constexpr int kReturnCount = return_count; \
enum ParameterIndices { \
__dummy = -1, /* to be able to pass zero arguments */ \
##__VA_ARGS__, \
\
kParameterCount \
};
// This is valid only for builtins that use EntryFrame, which does not scan // This is valid only for builtins that use EntryFrame, which does not scan
// stack arguments on GC. // stack arguments on GC.
...@@ -437,10 +436,17 @@ STATIC_ASSERT(kMaxTFSBuiltinRegisterParams <= kMaxBuiltinRegisterParams); ...@@ -437,10 +436,17 @@ STATIC_ASSERT(kMaxTFSBuiltinRegisterParams <= kMaxBuiltinRegisterParams);
kParameterCount \ kParameterCount \
}; };
#define DEFINE_PARAMETERS(...) DEFINE_RESULT_AND_PARAMETERS(1, ##__VA_ARGS__) #define DEFINE_PARAMETERS(...) \
DEFINE_FLAGS_AND_RESULT_AND_PARAMETERS( \
CallInterfaceDescriptorData::kNoFlags, 1, ##__VA_ARGS__)
#define DEFINE_PARAMETERS_NO_CONTEXT(...) \ #define DEFINE_PARAMETERS_NO_CONTEXT(...) \
DEFINE_RESULT_AND_PARAMETERS_NO_CONTEXT(1, ##__VA_ARGS__) DEFINE_FLAGS_AND_RESULT_AND_PARAMETERS( \
CallInterfaceDescriptorData::kNoContext, 1, ##__VA_ARGS__)
#define DEFINE_PARAMETERS_VARARGS(...) \
DEFINE_FLAGS_AND_RESULT_AND_PARAMETERS( \
CallInterfaceDescriptorData::kAllowVarArgs, 1, ##__VA_ARGS__)
#define DEFINE_RESULT_AND_PARAMETER_TYPES(...) \ #define DEFINE_RESULT_AND_PARAMETER_TYPES(...) \
void InitializePlatformIndependent(CallInterfaceDescriptorData* data) \ void InitializePlatformIndependent(CallInterfaceDescriptorData* data) \
...@@ -460,7 +466,7 @@ STATIC_ASSERT(kMaxTFSBuiltinRegisterParams <= kMaxBuiltinRegisterParams); ...@@ -460,7 +466,7 @@ STATIC_ASSERT(kMaxTFSBuiltinRegisterParams <= kMaxBuiltinRegisterParams);
#define DEFINE_JS_PARAMETERS(...) \ #define DEFINE_JS_PARAMETERS(...) \
static constexpr int kDescriptorFlags = \ static constexpr int kDescriptorFlags = \
CallInterfaceDescriptorData::kNoFlags; \ CallInterfaceDescriptorData::kAllowVarArgs; \
static constexpr int kReturnCount = 1; \ static constexpr int kReturnCount = 1; \
enum ParameterIndices { \ enum ParameterIndices { \
kTarget, \ kTarget, \
...@@ -843,7 +849,7 @@ class TypeofDescriptor : public CallInterfaceDescriptor { ...@@ -843,7 +849,7 @@ class TypeofDescriptor : public CallInterfaceDescriptor {
class CallTrampolineDescriptor : public CallInterfaceDescriptor { class CallTrampolineDescriptor : public CallInterfaceDescriptor {
public: public:
DEFINE_PARAMETERS(kFunction, kActualArgumentsCount) DEFINE_PARAMETERS_VARARGS(kFunction, kActualArgumentsCount)
DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kFunction DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kFunction
MachineType::Int32()) // kActualArgumentsCount MachineType::Int32()) // kActualArgumentsCount
DECLARE_DESCRIPTOR(CallTrampolineDescriptor, CallInterfaceDescriptor) DECLARE_DESCRIPTOR(CallTrampolineDescriptor, CallInterfaceDescriptor)
...@@ -871,7 +877,7 @@ class CallForwardVarargsDescriptor : public CallInterfaceDescriptor { ...@@ -871,7 +877,7 @@ class CallForwardVarargsDescriptor : public CallInterfaceDescriptor {
class CallFunctionTemplateDescriptor : public CallInterfaceDescriptor { class CallFunctionTemplateDescriptor : public CallInterfaceDescriptor {
public: public:
DEFINE_PARAMETERS(kFunctionTemplateInfo, kArgumentsCount) DEFINE_PARAMETERS_VARARGS(kFunctionTemplateInfo, kArgumentsCount)
DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kFunctionTemplateInfo DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kFunctionTemplateInfo
MachineType::IntPtr()) // kArgumentsCount MachineType::IntPtr()) // kArgumentsCount
DECLARE_DESCRIPTOR(CallFunctionTemplateDescriptor, CallInterfaceDescriptor) DECLARE_DESCRIPTOR(CallFunctionTemplateDescriptor, CallInterfaceDescriptor)
...@@ -1087,8 +1093,8 @@ class CEntry1ArgvOnStackDescriptor : public CallInterfaceDescriptor { ...@@ -1087,8 +1093,8 @@ class CEntry1ArgvOnStackDescriptor : public CallInterfaceDescriptor {
class ApiCallbackDescriptor : public CallInterfaceDescriptor { class ApiCallbackDescriptor : public CallInterfaceDescriptor {
public: public:
DEFINE_PARAMETERS(kApiFunctionAddress, kActualArgumentsCount, kCallData, DEFINE_PARAMETERS_VARARGS(kApiFunctionAddress, kActualArgumentsCount,
kHolder) kCallData, kHolder)
// receiver is implicit stack argument 1 // receiver is implicit stack argument 1
// argv are implicit stack arguments [2, 2 + kArgc[ // argv are implicit stack arguments [2, 2 + kArgc[
DEFINE_PARAMETER_TYPES(MachineType::Pointer(), // kApiFunctionAddress DEFINE_PARAMETER_TYPES(MachineType::Pointer(), // kApiFunctionAddress
...@@ -1364,9 +1370,10 @@ BUILTIN_LIST_TFS(DEFINE_TFS_BUILTIN_DESCRIPTOR) ...@@ -1364,9 +1370,10 @@ BUILTIN_LIST_TFS(DEFINE_TFS_BUILTIN_DESCRIPTOR)
#undef DECLARE_DESCRIPTOR_WITH_BASE #undef DECLARE_DESCRIPTOR_WITH_BASE
#undef DECLARE_DESCRIPTOR #undef DECLARE_DESCRIPTOR
#undef DECLARE_JS_COMPATIBLE_DESCRIPTOR #undef DECLARE_JS_COMPATIBLE_DESCRIPTOR
#undef DEFINE_FLAGS_AND_RESULT_AND_PARAMETERS
#undef DEFINE_RESULT_AND_PARAMETERS #undef DEFINE_RESULT_AND_PARAMETERS
#undef DEFINE_RESULT_AND_PARAMETERS_NO_CONTEXT
#undef DEFINE_PARAMETERS #undef DEFINE_PARAMETERS
#undef DEFINE_PARAMETERS_VARARGS
#undef DEFINE_PARAMETERS_NO_CONTEXT #undef DEFINE_PARAMETERS_NO_CONTEXT
#undef DEFINE_RESULT_AND_PARAMETER_TYPES #undef DEFINE_RESULT_AND_PARAMETER_TYPES
#undef DEFINE_PARAMETER_TYPES #undef DEFINE_PARAMETER_TYPES
......
...@@ -1310,7 +1310,13 @@ Node* CodeAssembler::CallStubN(StubCallMode call_mode, ...@@ -1310,7 +1310,13 @@ Node* CodeAssembler::CallStubN(StubCallMode call_mode,
int implicit_nodes = descriptor.HasContextParameter() ? 2 : 1; int implicit_nodes = descriptor.HasContextParameter() ? 2 : 1;
DCHECK_LE(implicit_nodes, input_count); DCHECK_LE(implicit_nodes, input_count);
int argc = input_count - implicit_nodes; int argc = input_count - implicit_nodes;
#ifdef DEBUG
if (descriptor.AllowVarArgs()) {
DCHECK_LE(descriptor.GetParameterCount(), argc); DCHECK_LE(descriptor.GetParameterCount(), argc);
} else {
DCHECK_EQ(descriptor.GetParameterCount(), argc);
}
#endif
// Extra arguments not mentioned in the descriptor are passed on the stack. // Extra arguments not mentioned in the descriptor are passed on the stack.
int stack_parameter_count = argc - descriptor.GetRegisterParameterCount(); int stack_parameter_count = argc - descriptor.GetRegisterParameterCount();
DCHECK_LE(descriptor.GetStackParameterCount(), stack_parameter_count); DCHECK_LE(descriptor.GetStackParameterCount(), stack_parameter_count);
......
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