-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang] Fix crash with multiple non-parenthsized sizeof
#101297
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: Vlad Serebrennikov (Endilll) ChangesThere are 5 unary operators that can be followed by a non-parenthesized expression: Fixes #45061 Full diff: https://github.com/llvm/llvm-project/pull/101297.diff 2 Files Affected:
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index e82b565272831..e501d5e91e77d 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -2479,7 +2479,19 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
return ExprError();
}
- Operand = ParseCastExpression(UnaryExprOnly);
+ // If we're parsing a chain that consists of keywords that could be
+ // followed by a non-parenthesized expression, BalancedDelimiterTracker
+ // is not going to help when the nesting is too deep. In this corner case
+ // we continue to parse with sufficient stack space to avoid crashing.
+ if (OpTok.isOneOf(tok::kw_sizeof, tok::kw___datasizeof, tok::kw___alignof,
+ tok::kw_alignof, tok::kw__Alignof) &&
+ Tok.isOneOf(tok::kw_sizeof, tok::kw___datasizeof, tok::kw___alignof,
+ tok::kw_alignof, tok::kw__Alignof))
+ Actions.runWithSufficientStackSpace(Tok.getLocation(), [&] {
+ Operand = ParseCastExpression(UnaryExprOnly);
+ });
+ else
+ Operand = ParseCastExpression(UnaryExprOnly);
} else {
// If it starts with a '(', we know that it is either a parenthesized
// type-name, or it is a unary-expression that starts with a compound
diff --git a/clang/test/Parser/parser-overflow-non-parenthesized.c b/clang/test/Parser/parser-overflow-non-parenthesized.c
new file mode 100644
index 0000000000000..b6c7485274090
--- /dev/null
+++ b/clang/test/Parser/parser-overflow-non-parenthesized.c
@@ -0,0 +1,135 @@
+// RUN: %clang_cc1 %s 2>&1 | FileCheck %s
+
+void f(void) {
+ // 600 sizeof's
+ int a =
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof sizeof
+ 0;
+ (void)a;
+
+ // 600 of sizeof and __alignof
+ int b =
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof sizeof __alignof
+ 0;
+ (void)b;
+}
+
+// CHECK: warning: stack nearly exhausted; compilation time may suffer, and crashes due to stack overflow are likely
|
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.
For reference, we explored whether this could be done by using tail-call elimination (it can't, at least not in any straightforward way); the peek-ahead approach was the best tradeoff we could find. (We peek ahead to try to limit the performance issues to folks doing sizeof sizeof ...
which should hopefully be a pretty rare situation given that will always result in sizeof(size_t)
.)
Testing for stack exhaustion is always a challenge and so it is reasonable for this to not come with a test case. However, did you manually verify that it fixes the crash for you?
The changes LGTM, but please keep an eye on the LLVM compile time tracker once this lands to see whether peeking ahead introduced some significant performance issue we didn't expect.
Yes, the test I originally included wasn't passing without my fix, but passed with my fix locally. |
There are 5 unary operators that can be followed by a non-parenthesized expression:
sizeof
,__datasizeof
,__alignof
,alignof
,_Alignof
. When we nest them too deep,BalancedDelimiterTracker
does not help, because there are no parentheses, and we crash. Instead, this patch recognize chains of those operators, and parse them with sufficient stack space.Fixes #45061