https://github.com/mygitljf updated 
https://github.com/llvm/llvm-project/pull/199098

>From 08edf9e90a4d4e6c812a8b52c43ee58dc8c4591a Mon Sep 17 00:00:00 2001
From: mygitljf <[email protected]>
Date: Thu, 21 May 2026 19:31:48 +0000
Subject: [PATCH 1/2] [clang-format] Fix a crash on unbalanced `?` inside
 nested braces

When `parseConditional` searches for the `:` of a ternary expression,
it would unconditionally feed every token to `consumeToken`. On
malformed input where a `}` reaches the ternary parser before any `:`,
`consumeToken`'s `tok::r_brace` branch pops a `Scopes` frame owned by
an enclosing `parseBrace`, leaving `Scopes` inconsistent with the
actual brace nesting and tripping `assert(!Scopes.empty())` at the top
of `parseBrace`'s loop on the next iteration.

Bail out of `parseConditional` on an unbalanced `}` so the closing
brace propagates up to the enclosing `parseBrace`, which pops the
matching frame through its normal path. This mirrors the existing
defensive check in `parseAngle` (TokenAnnotator.cpp:247).

Fixes #199017
---
 clang/lib/Format/TokenAnnotator.cpp   | 5 +++++
 clang/unittests/Format/FormatTest.cpp | 2 ++
 2 files changed, 7 insertions(+)

diff --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index 43e4f6796b6dd..c3a65fd9eedb5 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -1297,6 +1297,11 @@ class AnnotatingParser {
         next();
         return true;
       }
+      // Avoid consuming an unbalanced `}` here: it would pop a Scopes frame
+      // owned by an enclosing parseBrace and trip its `!Scopes.empty()`
+      // assertion. See Issue #199017.
+      if (CurrentToken->is(tok::r_brace))
+        return false;
       if (!consumeToken())
         return false;
     }
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 83e2c5b38ceaf..41b5605ef1b9e 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -14383,6 +14383,8 @@ TEST_F(FormatTest, IncorrectCodeUnbalancedBraces) {
                 "};");
   verifyNoCrash("decltype( {\n"
                 "  {");
+  // Issue #199017
+  verifyNoCrash("{{ < ? } a} b");
 }
 
 TEST_F(FormatTest, IncorrectUnbalancedBracesInMacrosWithUnicode) {

>From 5004f7091171238c9cb35c1c4920f49574e29942 Mon Sep 17 00:00:00 2001
From: mygitljf <[email protected]>
Date: Sat, 23 May 2026 12:03:54 +0000
Subject: [PATCH 2/2] modify comments and move the position of verifyNoCrash

---
 clang/lib/Format/TokenAnnotator.cpp   | 6 +++---
 clang/unittests/Format/FormatTest.cpp | 3 +--
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index c3a65fd9eedb5..00b3fc0ad7eaa 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -1297,9 +1297,9 @@ class AnnotatingParser {
         next();
         return true;
       }
-      // Avoid consuming an unbalanced `}` here: it would pop a Scopes frame
-      // owned by an enclosing parseBrace and trip its `!Scopes.empty()`
-      // assertion. See Issue #199017.
+      // A `}` here would be consumed by consumeToken's r_brace branch
+      // and pop a Scopes frame owned by the enclosing parseBrace, leaving
+      // the Scopes stack out of sync with the actual brace nesting.
       if (CurrentToken->is(tok::r_brace))
         return false;
       if (!consumeToken())
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 41b5605ef1b9e..11d649af53359 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -14383,8 +14383,6 @@ TEST_F(FormatTest, IncorrectCodeUnbalancedBraces) {
                 "};");
   verifyNoCrash("decltype( {\n"
                 "  {");
-  // Issue #199017
-  verifyNoCrash("{{ < ? } a} b");
 }
 
 TEST_F(FormatTest, IncorrectUnbalancedBracesInMacrosWithUnicode) {
@@ -22510,6 +22508,7 @@ TEST_F(FormatTest, DoNotCrashOnInvalidInput) {
   verifyNoCrash("        tst     %o5     ! are we doing the gray case?\n"
                 "LY52:                   ! [internal]");
   verifyNoCrash("operator foo *;");
+  verifyNoCrash("{{ < ? } a} b");
 }
 
 TEST_F(FormatTest, FormatsTableGenCode) {

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to