-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[clang] Fix Variable Length Array _Countof
Crash
#154627
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang Author: Vincent (Mr-Anyone) ChangesCheck for missing VLA size expressions (e.g. in int a[*][10]) before evaluation to avoid crashes in _Countof and constant expression checks. fixes #152826 Full diff: https://github.com/llvm/llvm-project/pull/154627.diff 4 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index e88d68fa99664..df738db771e33 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -200,6 +200,8 @@ Bug Fixes in This Version
-------------------------
- Fix a crash when marco name is empty in ``#pragma push_macro("")`` or
``#pragma pop_macro("")``. (#GH149762).
+- Fix a crash in variable length array (e.g. int a[*]) function parameter type
+ being used in `_Countof` expression. (#GH152826)
- `-Wunreachable-code`` now diagnoses tautological or contradictory
comparisons such as ``x != 0 || x != 1.0`` and ``x == 0 && x == 1.0`` on
targets that treat ``_Float16``/``__fp16`` as native scalar types. Previously
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index e3235d34e230e..7881afc4bb6f5 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -2248,7 +2248,9 @@ bool Compiler<Emitter>::VisitUnaryExprOrTypeTraitExpr(
assert(VAT);
if (VAT->getElementType()->isArrayType()) {
std::optional<APSInt> Res =
- VAT->getSizeExpr()->getIntegerConstantExpr(ASTCtx);
+ VAT->getSizeExpr()
+ ? VAT->getSizeExpr()->getIntegerConstantExpr(ASTCtx)
+ : std::nullopt;
if (Res) {
if (DiscardResult)
return true;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 9c87a88899647..1d939cf9655d4 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -15345,6 +15345,13 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
const auto *VAT = Info.Ctx.getAsVariableArrayType(Ty);
assert(VAT);
if (VAT->getElementType()->isArrayType()) {
+ // Variable array size expression could be missing (e.g. int a[*][10]) In
+ // that case, it can't be a constant expression
+ if (!VAT->getSizeExpr()) {
+ Info.FFDiag(E->getBeginLoc());
+ return false;
+ }
+
std::optional<APSInt> Res =
VAT->getSizeExpr()->getIntegerConstantExpr(Info.Ctx);
if (Res) {
@@ -17867,7 +17874,10 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
// it is an ICE or not.
const auto *VAT = Ctx.getAsVariableArrayType(ArgTy);
if (VAT->getElementType()->isArrayType())
- return CheckICE(VAT->getSizeExpr(), Ctx);
+ // Variable array size expression could be missing (e.g. int a[*][10])
+ // In that case, it can't be a constant expression
+ return VAT->getSizeExpr() ? CheckICE(VAT->getSizeExpr(), Ctx)
+ : ICEDiag(IK_NotICE, E->getBeginLoc());
// Otherwise, this is a regular VLA, which is definitely not an ICE.
return ICEDiag(IK_NotICE, E->getBeginLoc());
diff --git a/clang/test/Sema/gh152826.c b/clang/test/Sema/gh152826.c
new file mode 100644
index 0000000000000..a7d5f0138ad5d
--- /dev/null
+++ b/clang/test/Sema/gh152826.c
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -std=c2y -verify %s
+// RUN: %clang_cc1 -std=c2y -verify -fexperimental-new-constant-interpreter %s
+// expected-no-diagnostics
+
+void gh152826(char (*a)[*][5], int (*x)[_Countof (*a)]);
+void more_likely_in_practice(unsigned long size_one, int (*a)[*][5], int b[_Countof(*a)]);
|
clang/test/Sema/gh152826.c
Outdated
// RUN: %clang_cc1 -std=c2y -verify -fexperimental-new-constant-interpreter %s | ||
// expected-no-diagnostics | ||
|
||
void gh152826(char (*a)[*][5], int (*x)[_Countof (*a)]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a test for e.g.
void f(int x[*][1][*][2][*][*][3][*], int q[_Countof(*x)]);
to make sure we handle nested VLAs properly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also add a codegen test to verify that we emit the correct LLVM IR to runtime evaluate the _Countof
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to make sure we handle nested VLAs properly.
Sure.
We should also add a codegen test to verify that we emit the correct LLVM IR to runtime evaluate the _Countof
I am not sure how you would go about doing that. Because [*]
seems to only appear in function prototypes and not definitions. godbolt
C23 6.7.7.4: If the function declarator is not part of a definition of that function, parameters [...] may use the [*] notation in their sequences of declarator specifiers to specify variable length array types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought there was a way we could end up having to evaluate here, but now I think you're right, that doesn't seem to be possible. So nevermind! :-)
clang/docs/ReleaseNotes.rst
Outdated
- Fix a crash in variable length array (e.g. int a[*]) function parameter type | ||
being used in `_Countof` expression. (#GH152826) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Fix a crash in variable length array (e.g. int a[*]) function parameter type | |
being used in `_Countof` expression. (#GH152826) | |
- Fix a crash in variable length array (e.g. ``int a[*]``) function parameter type | |
being used in ``_Countof`` expression. (#GH152826) |
Also, RST...
clang/lib/AST/ExprConstant.cpp
Outdated
@@ -15345,6 +15345,13 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr( | |||
const auto *VAT = Info.Ctx.getAsVariableArrayType(Ty); | |||
assert(VAT); | |||
if (VAT->getElementType()->isArrayType()) { | |||
// Variable array size expression could be missing (e.g. int a[*][10]) In | |||
// that case, it can't be a constant expression |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// that case, it can't be a constant expression | |
// that case, it can't be a constant expression. |
clang/test/Sema/gh152826.c
Outdated
// RUN: %clang_cc1 -std=c2y -verify -fexperimental-new-constant-interpreter %s | ||
// expected-no-diagnostics | ||
|
||
void gh152826(char (*a)[*][5], int (*x)[_Countof (*a)]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also add a codegen test to verify that we emit the correct LLVM IR to runtime evaluate the _Countof
a2064bc
to
cd9e0fb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
clang/test/Sema/gh152826.c
Outdated
// RUN: %clang_cc1 -std=c2y -verify -fexperimental-new-constant-interpreter %s | ||
// expected-no-diagnostics | ||
|
||
void gh152826(char (*a)[*][5], int (*x)[_Countof (*a)]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought there was a way we could end up having to evaluate here, but now I think you're right, that doesn't seem to be possible. So nevermind! :-)
clang/docs/ReleaseNotes.rst
Outdated
@@ -222,6 +222,8 @@ Bug Fixes in This Version | |||
------------------------- | |||
- Fix a crash when marco name is empty in ``#pragma push_macro("")`` or | |||
``#pragma pop_macro("")``. (#GH149762). | |||
- Fix a crash in variable length array (e.g. ``int a[*]``) function parameter type | |||
being used in ``_Countof`` expression. (#GH152826) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
being used in ``_Countof`` expression. (#GH152826) | |
being used in ``_Countof`` expression. (#GH152826). |
clang/test/Sema/gh152826.c
Outdated
// RUN: %clang_cc1 -std=c2y -verify -fexperimental-new-constant-interpreter %s | ||
// expected-no-diagnostics | ||
|
||
void gh152826(char (*a)[*][5], int (*x)[_Countof (*a)]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
void gh152826(char (*a)[*][5], int (*x)[_Countof (*a)]); | |
void gh152826(char (*a)[*][5], int (*x)[_Countof(*a)]); |
d4190aa
to
2c8b558
Compare
Check for missing VLA size expressions (e.g. in int a[*][10]) before evaluation to avoid crashes in _Countof and constant expression checks. fixes llvm#152826
18fe45c
to
67afe21
Compare
Thanks for the review. I don't have merge access. It would be nice if you can merge this for me. Thanks |
Check for missing VLA size expressions (e.g. in int a[*][10]) before evaluation to avoid crashes in _Countof and constant expression checks.
fixes #152826