[clang] [clang] Fix crash with multiple non-parenthsized `sizeof` (PR #101297)

via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 31 00:34:16 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Vlad Serebrennikov (Endilll)

<details>
<summary>Changes</summary>

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

---
Full diff: https://github.com/llvm/llvm-project/pull/101297.diff


2 Files Affected:

- (modified) clang/lib/Parse/ParseExpr.cpp (+13-1) 
- (added) clang/test/Parser/parser-overflow-non-parenthesized.c (+135) 


``````````diff
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

``````````

</details>


https://github.com/llvm/llvm-project/pull/101297


More information about the cfe-commits mailing list