[clang] [clang] Diagnose functions with too many parameters (PR #104833)
Vlad Serebrennikov via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 21 05:21:30 PDT 2024
https://github.com/Endilll updated https://github.com/llvm/llvm-project/pull/104833
>From 424818620766cedb2770e076ee359afeb0cc14ec Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Mon, 19 Aug 2024 19:26:46 +0300
Subject: [PATCH 1/7] Add in-loop check
---
clang/include/clang/AST/Type.h | 7 ++++++-
clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 +++
clang/lib/Parse/ParseDecl.cpp | 10 ++++++++++
3 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 27618604192c51..575f3c17a3f691 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1929,6 +1929,11 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
unsigned Kind : NumOfBuiltinTypeBits;
};
+public:
+ static constexpr int FunctionTypeNumParamsWidth = 16;
+ static constexpr int FunctionTypeNumParamsLimit = (1 << 16) - 1;
+
+protected:
/// FunctionTypeBitfields store various bits belonging to FunctionProtoType.
/// Only common bits are stored here. Additional uncommon bits are stored
/// in a trailing object after FunctionProtoType.
@@ -1966,7 +1971,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
/// According to [implimits] 8 bits should be enough here but this is
/// somewhat easy to exceed with metaprogramming and so we would like to
/// keep NumParams as wide as reasonably possible.
- unsigned NumParams : 16;
+ unsigned NumParams : FunctionTypeNumParamsWidth;
/// The type of exception specification this function has.
LLVM_PREFERRED_TYPE(ExceptionSpecificationType)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8a92973236ddbd..1f97db2e13ebf9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9311,6 +9311,9 @@ def note_constinit_missing_here : Note<
def err_dimension_expr_not_constant_integer : Error<
"dimension expression does not evaluate to a constant unsigned int">;
+def err_function_parameter_limit_exceeded : Error<
+ "too many function parameters; subsequent parameters are skipped">;
+
def err_typecheck_cond_incompatible_operands_null : Error<
"non-pointer operand type %0 incompatible with %select{NULL|nullptr}1">;
def ext_empty_struct_union : Extension<
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index a8a9d3f3f5b088..94f2366d484f2d 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -8025,6 +8025,16 @@ void Parser::ParseParameterDeclarationClause(
// Consume the keyword.
ConsumeToken();
}
+
+ // FunctionTypeBitfields::NumParams can only hold so much.
+ // Skip until the the end of the parameter list, ignoring
+ // parameters that would overflow.
+ if (ParamInfo.size() == Type::FunctionTypeNumParamsLimit) {
+ Diag(ParmDeclarator.getBeginLoc(), diag::err_function_parameter_limit_exceeded);
+ SkipUntil(tok::r_paren, SkipUntilFlags::StopBeforeMatch);
+ break;
+ }
+
// Inform the actions module about the parameter declarator, so it gets
// added to the current scope.
Decl *Param =
>From 11c54d40f39005ac20f8fb212981bc443a197ed8 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Mon, 19 Aug 2024 21:30:35 +0300
Subject: [PATCH 2/7] Add a test and a release note
---
clang/docs/ReleaseNotes.rst | 3 ++
.../test/Parser/function-parameter-limit.cpp | 29 +++++++++++++++++++
2 files changed, 32 insertions(+)
create mode 100644 clang/test/Parser/function-parameter-limit.cpp
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a4257ea1f48c11..e1ab1d45bed766 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -288,6 +288,9 @@ Miscellaneous Clang Crashes Fixed
- Fixed a crash caused by long chains of ``sizeof`` and other similar operators
that can be followed by a non-parenthesized expression. (#GH45061)
+- Fixed a crash when function has more than 65536 parameters.
+ Now a diagnostic is emitted. (#GH35741)
+
OpenACC Specific Changes
------------------------
diff --git a/clang/test/Parser/function-parameter-limit.cpp b/clang/test/Parser/function-parameter-limit.cpp
new file mode 100644
index 00000000000000..c6917c51644187
--- /dev/null
+++ b/clang/test/Parser/function-parameter-limit.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -verify %s
+
+#define P_10(x) x##0, x##1, x##2, x##3, x##4, x##5, x##6, x##7, x##8, x##9,
+#define P_100(x) P_10(x##0) P_10(x##1) P_10(x##2) P_10(x##3) P_10(x##4) \
+ P_10(x##5) P_10(x##6) P_10(x##7) P_10(x##8) P_10(x##9)
+#define P_1000(x) P_100(x##0) P_100(x##1) P_100(x##2) P_100(x##3) P_100(x##4) \
+ P_100(x##5) P_100(x##6) P_100(x##7) P_100(x##8) P_100(x##9)
+#define P_10000(x) P_1000(x##0) P_1000(x##1) P_1000(x##2) P_1000(x##3) P_1000(x##4) \
+ P_1000(x##5) P_1000(x##6) P_1000(x##7) P_1000(x##8) P_1000(x##9)
+
+void func (
+ P_10000(int p)
+ P_10000(int q)
+ P_10000(int r)
+ P_10000(int s)
+ P_10000(int t)
+ P_10000(int u)
+ P_10000(int v) // expected-error {{too many function parameters; subsequent parameters are skipped}}
+ int w);
+
+extern double(*func2)(
+ P_10000(int p)
+ P_10000(int q)
+ P_10000(int r)
+ P_10000(int s)
+ P_10000(int t)
+ P_10000(int u)
+ P_10000(int v) // expected-error {{too many function parameters; subsequent parameters are skipped}}
+ int w);
\ No newline at end of file
>From 20929235140bb2b97cbc80458c081d5572dcc089 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Mon, 19 Aug 2024 21:49:42 +0300
Subject: [PATCH 3/7] Run clang-format
---
clang/lib/Parse/ParseDecl.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 94f2366d484f2d..105f41276f67ab 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -8030,7 +8030,8 @@ void Parser::ParseParameterDeclarationClause(
// Skip until the the end of the parameter list, ignoring
// parameters that would overflow.
if (ParamInfo.size() == Type::FunctionTypeNumParamsLimit) {
- Diag(ParmDeclarator.getBeginLoc(), diag::err_function_parameter_limit_exceeded);
+ Diag(ParmDeclarator.getBeginLoc(),
+ diag::err_function_parameter_limit_exceeded);
SkipUntil(tok::r_paren, SkipUntilFlags::StopBeforeMatch);
break;
}
>From 5775814e8dd7f4724d18f6ea2ff1477feef814c6 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Mon, 19 Aug 2024 21:56:33 +0300
Subject: [PATCH 4/7] Add a newline
---
clang/test/Parser/function-parameter-limit.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/Parser/function-parameter-limit.cpp b/clang/test/Parser/function-parameter-limit.cpp
index c6917c51644187..4493b1e0f0ffdf 100644
--- a/clang/test/Parser/function-parameter-limit.cpp
+++ b/clang/test/Parser/function-parameter-limit.cpp
@@ -26,4 +26,4 @@ extern double(*func2)(
P_10000(int t)
P_10000(int u)
P_10000(int v) // expected-error {{too many function parameters; subsequent parameters are skipped}}
- int w);
\ No newline at end of file
+ int w);
>From 257a7eb6e95a1310d4644990b9bedd697c8714d4 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Mon, 19 Aug 2024 22:02:40 +0300
Subject: [PATCH 5/7] Replace tabs with spaces
---
clang/test/Parser/function-parameter-limit.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/test/Parser/function-parameter-limit.cpp b/clang/test/Parser/function-parameter-limit.cpp
index 4493b1e0f0ffdf..9f66a01456b831 100644
--- a/clang/test/Parser/function-parameter-limit.cpp
+++ b/clang/test/Parser/function-parameter-limit.cpp
@@ -2,11 +2,11 @@
#define P_10(x) x##0, x##1, x##2, x##3, x##4, x##5, x##6, x##7, x##8, x##9,
#define P_100(x) P_10(x##0) P_10(x##1) P_10(x##2) P_10(x##3) P_10(x##4) \
- P_10(x##5) P_10(x##6) P_10(x##7) P_10(x##8) P_10(x##9)
+ P_10(x##5) P_10(x##6) P_10(x##7) P_10(x##8) P_10(x##9)
#define P_1000(x) P_100(x##0) P_100(x##1) P_100(x##2) P_100(x##3) P_100(x##4) \
- P_100(x##5) P_100(x##6) P_100(x##7) P_100(x##8) P_100(x##9)
+ P_100(x##5) P_100(x##6) P_100(x##7) P_100(x##8) P_100(x##9)
#define P_10000(x) P_1000(x##0) P_1000(x##1) P_1000(x##2) P_1000(x##3) P_1000(x##4) \
- P_1000(x##5) P_1000(x##6) P_1000(x##7) P_1000(x##8) P_1000(x##9)
+ P_1000(x##5) P_1000(x##6) P_1000(x##7) P_1000(x##8) P_1000(x##9)
void func (
P_10000(int p)
>From 7d24668f48fe367e264eb67374041b9e6ee391d2 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Mon, 19 Aug 2024 23:57:29 +0300
Subject: [PATCH 6/7] Incorporate Corentin's suggestions
---
clang/include/clang/Basic/DiagnosticParseKinds.td | 3 +++
clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 ---
clang/lib/Parse/ParseDecl.cpp | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 62a97b36737e72..464f08637332d4 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -481,6 +481,9 @@ def ext_decomp_decl_empty : ExtWarn<
"ISO C++17 does not allow a decomposition group to be empty">,
InGroup<DiagGroup<"empty-decomposition">>;
+def err_function_parameter_limit_exceeded : Error<
+ "too many function parameters; subsequent parameters will be ignored">;
+
// C++26 structured bindings
def ext_decl_attrs_on_binding : ExtWarn<
"an attribute specifier sequence attached to a structured binding declaration "
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1f97db2e13ebf9..8a92973236ddbd 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9311,9 +9311,6 @@ def note_constinit_missing_here : Note<
def err_dimension_expr_not_constant_integer : Error<
"dimension expression does not evaluate to a constant unsigned int">;
-def err_function_parameter_limit_exceeded : Error<
- "too many function parameters; subsequent parameters are skipped">;
-
def err_typecheck_cond_incompatible_operands_null : Error<
"non-pointer operand type %0 incompatible with %select{NULL|nullptr}1">;
def ext_empty_struct_union : Extension<
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 105f41276f67ab..ed5d6ce90aa7d1 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -8026,7 +8026,7 @@ void Parser::ParseParameterDeclarationClause(
ConsumeToken();
}
- // FunctionTypeBitfields::NumParams can only hold so much.
+ // We can only store so many parameters
// Skip until the the end of the parameter list, ignoring
// parameters that would overflow.
if (ParamInfo.size() == Type::FunctionTypeNumParamsLimit) {
>From dce5cce1133a8aaac4e2b7abdba3e85bcf3853bc Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Wed, 21 Aug 2024 15:21:08 +0300
Subject: [PATCH 7/7] Update the test with new diagnostic wording
---
clang/test/Parser/function-parameter-limit.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/test/Parser/function-parameter-limit.cpp b/clang/test/Parser/function-parameter-limit.cpp
index 9f66a01456b831..29f5dde294715c 100644
--- a/clang/test/Parser/function-parameter-limit.cpp
+++ b/clang/test/Parser/function-parameter-limit.cpp
@@ -15,7 +15,7 @@ void func (
P_10000(int s)
P_10000(int t)
P_10000(int u)
- P_10000(int v) // expected-error {{too many function parameters; subsequent parameters are skipped}}
+ P_10000(int v) // expected-error {{too many function parameters; subsequent parameters will be ignored}}
int w);
extern double(*func2)(
@@ -25,5 +25,5 @@ extern double(*func2)(
P_10000(int s)
P_10000(int t)
P_10000(int u)
- P_10000(int v) // expected-error {{too many function parameters; subsequent parameters are skipped}}
+ P_10000(int v) // expected-error {{too many function parameters; subsequent parameters will be ignored}}
int w);
More information about the cfe-commits
mailing list