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 {
enum Flag {
kNoFlags = 0u,
kNoContext = 1u << 0,
// 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
// untagged stack arguments.
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>;
......@@ -249,6 +252,10 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptor {
return (flags() & CallInterfaceDescriptorData::kNoContext) == 0;
}
bool AllowVarArgs() const {
return flags() & CallInterfaceDescriptorData::kAllowVarArgs;
}
int GetReturnCount() const { return data()->return_count(); }
MachineType GetReturnType(int index) const {
......@@ -400,28 +407,20 @@ STATIC_ASSERT(kMaxTFSBuiltinRegisterParams <= kMaxBuiltinRegisterParams);
\
public:
#define DEFINE_RESULT_AND_PARAMETERS(return_count, ...) \
static constexpr int kDescriptorFlags = \
CallInterfaceDescriptorData::kNoFlags; \
static constexpr int kReturnCount = return_count; \
enum ParameterIndices { \
__dummy = -1, /* to be able to pass zero arguments */ \
##__VA_ARGS__, \
\
kParameterCount, \
kContext = kParameterCount /* implicit parameter */ \
#define DEFINE_FLAGS_AND_RESULT_AND_PARAMETERS(flags, return_count, ...) \
static constexpr int kDescriptorFlags = flags; \
static constexpr int kReturnCount = return_count; \
enum ParameterIndices { \
__dummy = -1, /* to be able to pass zero arguments */ \
##__VA_ARGS__, \
\
kParameterCount, \
kContext = kParameterCount /* implicit parameter */ \
};
#define DEFINE_RESULT_AND_PARAMETERS_NO_CONTEXT(return_count, ...) \
static constexpr int kDescriptorFlags = \
CallInterfaceDescriptorData::kNoContext; \
static constexpr int kReturnCount = return_count; \
enum ParameterIndices { \
__dummy = -1, /* to be able to pass zero arguments */ \
##__VA_ARGS__, \
\
kParameterCount \
};
#define DEFINE_RESULT_AND_PARAMETERS(return_count, ...) \
DEFINE_FLAGS_AND_RESULT_AND_PARAMETERS( \
CallInterfaceDescriptorData::kNoFlags, return_count, ##__VA_ARGS__)
// This is valid only for builtins that use EntryFrame, which does not scan
// stack arguments on GC.
......@@ -437,10 +436,17 @@ STATIC_ASSERT(kMaxTFSBuiltinRegisterParams <= kMaxBuiltinRegisterParams);
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_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(...) \
void InitializePlatformIndependent(CallInterfaceDescriptorData* data) \
......@@ -460,7 +466,7 @@ STATIC_ASSERT(kMaxTFSBuiltinRegisterParams <= kMaxBuiltinRegisterParams);
#define DEFINE_JS_PARAMETERS(...) \
static constexpr int kDescriptorFlags = \
CallInterfaceDescriptorData::kNoFlags; \
CallInterfaceDescriptorData::kAllowVarArgs; \
static constexpr int kReturnCount = 1; \
enum ParameterIndices { \
kTarget, \
......@@ -843,7 +849,7 @@ class TypeofDescriptor : public CallInterfaceDescriptor {
class CallTrampolineDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kFunction, kActualArgumentsCount)
DEFINE_PARAMETERS_VARARGS(kFunction, kActualArgumentsCount)
DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kFunction
MachineType::Int32()) // kActualArgumentsCount
DECLARE_DESCRIPTOR(CallTrampolineDescriptor, CallInterfaceDescriptor)
......@@ -871,7 +877,7 @@ class CallForwardVarargsDescriptor : public CallInterfaceDescriptor {
class CallFunctionTemplateDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kFunctionTemplateInfo, kArgumentsCount)
DEFINE_PARAMETERS_VARARGS(kFunctionTemplateInfo, kArgumentsCount)
DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kFunctionTemplateInfo
MachineType::IntPtr()) // kArgumentsCount
DECLARE_DESCRIPTOR(CallFunctionTemplateDescriptor, CallInterfaceDescriptor)
......@@ -1087,8 +1093,8 @@ class CEntry1ArgvOnStackDescriptor : public CallInterfaceDescriptor {
class ApiCallbackDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kApiFunctionAddress, kActualArgumentsCount, kCallData,
kHolder)
DEFINE_PARAMETERS_VARARGS(kApiFunctionAddress, kActualArgumentsCount,
kCallData, kHolder)
// receiver is implicit stack argument 1
// argv are implicit stack arguments [2, 2 + kArgc[
DEFINE_PARAMETER_TYPES(MachineType::Pointer(), // kApiFunctionAddress
......@@ -1364,9 +1370,10 @@ BUILTIN_LIST_TFS(DEFINE_TFS_BUILTIN_DESCRIPTOR)
#undef DECLARE_DESCRIPTOR_WITH_BASE
#undef DECLARE_DESCRIPTOR
#undef DECLARE_JS_COMPATIBLE_DESCRIPTOR
#undef DEFINE_FLAGS_AND_RESULT_AND_PARAMETERS
#undef DEFINE_RESULT_AND_PARAMETERS
#undef DEFINE_RESULT_AND_PARAMETERS_NO_CONTEXT
#undef DEFINE_PARAMETERS
#undef DEFINE_PARAMETERS_VARARGS
#undef DEFINE_PARAMETERS_NO_CONTEXT
#undef DEFINE_RESULT_AND_PARAMETER_TYPES
#undef DEFINE_PARAMETER_TYPES
......
......@@ -1310,7 +1310,13 @@ Node* CodeAssembler::CallStubN(StubCallMode call_mode,
int implicit_nodes = descriptor.HasContextParameter() ? 2 : 1;
DCHECK_LE(implicit_nodes, input_count);
int argc = input_count - implicit_nodes;
DCHECK_LE(descriptor.GetParameterCount(), argc);
#ifdef DEBUG
if (descriptor.AllowVarArgs()) {
DCHECK_LE(descriptor.GetParameterCount(), argc);
} else {
DCHECK_EQ(descriptor.GetParameterCount(), argc);
}
#endif
// Extra arguments not mentioned in the descriptor are passed on the stack.
int stack_parameter_count = argc - descriptor.GetRegisterParameterCount();
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