https://github.com/LeGusto updated 
https://github.com/llvm/llvm-project/pull/206594

From 2012d864779c8a80e248e0c068db6dcf4f1bd2cb Mon Sep 17 00:00:00 2001
From: LeGusto <[email protected]>
Date: Tue, 30 Jun 2026 00:42:16 +0300
Subject: [PATCH 1/5] [clang-format] Fix crash on numeric literals with an
 incomplete exponent

NumericLiteralInfo computed the exponent/suffix search start from positions 
that can exceed the length of the string being searched (e.g. for `1e`, `1.0e`, 
`0xa.p`, `0x`, or `0x_`), so StringRef::find_insensitive and find_if_not read 
out of bounds -- an assertion failure on assertions-enabled builds and a silent 
out-of-bounds read otherwise. Clamp each search start to
the length of the string it indexes.

Fixes #206593
---
 clang/lib/Format/NumericLiteralInfo.cpp           | 14 +++++++++-----
 clang/unittests/Format/NumericLiteralCaseTest.cpp | 11 +++++++++++
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Format/NumericLiteralInfo.cpp 
b/clang/lib/Format/NumericLiteralInfo.cpp
index 81e6dd5e58bbc..0bd27f50efa8c 100644
--- a/clang/lib/Format/NumericLiteralInfo.cpp
+++ b/clang/lib/Format/NumericLiteralInfo.cpp
@@ -16,6 +16,7 @@
 
 #include "NumericLiteralInfo.h"
 #include "llvm/ADT/StringExtras.h"
+#include <algorithm>
 
 namespace clang {
 namespace format {
@@ -46,11 +47,13 @@ NumericLiteralInfo::NumericLiteralInfo(StringRef Text, char 
Separator) {
 
   // e.g. 1.e2 or 0xFp2
   const auto Pos = DotPos != StringRef::npos ? DotPos + 1 : BaseLetterPos + 2;
+  // Trim C++ user-defined suffix as in `1_Pa`.
+  const auto TrimmedText =
+      Separator == '\'' ? Text.take_front(Text.find('_')) : Text;
 
-  ExponentLetterPos =
-      // Trim C++ user-defined suffix as in `1_Pa`.
-      (Separator == '\'' ? Text.take_front(Text.find('_')) : Text)
-          .find_insensitive(IsHex ? 'p' : 'e', Pos);
+  // Clamp searches due to possible incomplete literals
+  ExponentLetterPos = TrimmedText.find_insensitive(
+      IsHex ? 'p' : 'e', std::min(Pos, TrimmedText.size()));
 
   const bool HasExponent = ExponentLetterPos != StringRef::npos;
   SuffixPos = Text.find_if_not(
@@ -58,7 +61,8 @@ NumericLiteralInfo::NumericLiteralInfo(StringRef Text, char 
Separator) {
         return (HasExponent || !IsHex ? isDigit : isHexDigit)(C) ||
                C == Separator;
       },
-      HasExponent ? ExponentLetterPos + 2 : Pos); // e.g. 1e-2f
+      HasExponent ? std::min(ExponentLetterPos + 2, Text.size())
+                  : std::min(Pos, Text.size())); // e.g. 1e-2f
 }
 
 } // namespace format
diff --git a/clang/unittests/Format/NumericLiteralCaseTest.cpp 
b/clang/unittests/Format/NumericLiteralCaseTest.cpp
index ecd230d73f692..afb321d8d1b14 100644
--- a/clang/unittests/Format/NumericLiteralCaseTest.cpp
+++ b/clang/unittests/Format/NumericLiteralCaseTest.cpp
@@ -340,6 +340,17 @@ TEST_F(NumericLiteralCaseTest, 
UnderScoreSeparatorLanguages) {
   verifyFormat("o = 0o0_10_010;", "o = 0O0_10_010;", Style);
 }
 
+TEST_F(NumericLiteralCaseTest, IncompleteLiteralDoesNotCrash) {
+  auto Style = getLLVMStyle();
+  Style.NumericLiteralCase.HexDigit = FormatStyle::NLCS_Upper;
+
+  verifyFormat("i = 1e;", Style);
+  verifyFormat("i = 1.0e;", Style);
+  verifyFormat("i = 0x1p;", Style);
+  verifyFormat("i = 0x;", Style);
+  verifyFormat("i = 0x_;", Style);
+}
+
 } // namespace
 } // namespace test
 } // namespace format

From da8ad592f41460357325f0e9c65347622341a6a9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gustas=20Janu=C5=A1onis?= <[email protected]>
Date: Tue, 30 Jun 2026 22:57:08 +0300
Subject: [PATCH 2/5] Apply suggestions from code review
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Björn Schäpers <[email protected]>
---
 clang/lib/Format/NumericLiteralInfo.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Format/NumericLiteralInfo.cpp 
b/clang/lib/Format/NumericLiteralInfo.cpp
index 0bd27f50efa8c..d4cfe95959759 100644
--- a/clang/lib/Format/NumericLiteralInfo.cpp
+++ b/clang/lib/Format/NumericLiteralInfo.cpp
@@ -51,7 +51,7 @@ NumericLiteralInfo::NumericLiteralInfo(StringRef Text, char 
Separator) {
   const auto TrimmedText =
       Separator == '\'' ? Text.take_front(Text.find('_')) : Text;
 
-  // Clamp searches due to possible incomplete literals
+  // Clamp searches due to possible incomplete literals.
   ExponentLetterPos = TrimmedText.find_insensitive(
       IsHex ? 'p' : 'e', std::min(Pos, TrimmedText.size()));
 
@@ -61,8 +61,7 @@ NumericLiteralInfo::NumericLiteralInfo(StringRef Text, char 
Separator) {
         return (HasExponent || !IsHex ? isDigit : isHexDigit)(C) ||
                C == Separator;
       },
-      HasExponent ? std::min(ExponentLetterPos + 2, Text.size())
-                  : std::min(Pos, Text.size())); // e.g. 1e-2f
+      std::min(HasExponent ? ExponentLetterPos + 2 : Pos, Text.size()); // 
e.g. 1e-2f
 }
 
 } // namespace format

From 157d690b5676ae7141a3b8d323a219beb51bb4fc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gustas=20Janu=C5=A1onis?= <[email protected]>
Date: Wed, 1 Jul 2026 00:56:19 +0300
Subject: [PATCH 3/5] closed parentheses

---
 clang/lib/Format/NumericLiteralInfo.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Format/NumericLiteralInfo.cpp 
b/clang/lib/Format/NumericLiteralInfo.cpp
index d4cfe95959759..5738193c7cc53 100644
--- a/clang/lib/Format/NumericLiteralInfo.cpp
+++ b/clang/lib/Format/NumericLiteralInfo.cpp
@@ -61,7 +61,7 @@ NumericLiteralInfo::NumericLiteralInfo(StringRef Text, char 
Separator) {
         return (HasExponent || !IsHex ? isDigit : isHexDigit)(C) ||
                C == Separator;
       },
-      std::min(HasExponent ? ExponentLetterPos + 2 : Pos, Text.size()); // 
e.g. 1e-2f
+      std::min(HasExponent ? ExponentLetterPos + 2 : Pos, Text.size())); // 
e.g. 1e-2f
 }
 
 } // namespace format

From 83ff7fa40e17e7ff1c25c9eaa895f58219e1ee4f Mon Sep 17 00:00:00 2001
From: LeGusto <[email protected]>
Date: Wed, 1 Jul 2026 08:42:42 +0300
Subject: [PATCH 4/5] applied clang-format HEAD~1

---
 clang/lib/Format/NumericLiteralInfo.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Format/NumericLiteralInfo.cpp 
b/clang/lib/Format/NumericLiteralInfo.cpp
index 5738193c7cc53..b4d0873cdc243 100644
--- a/clang/lib/Format/NumericLiteralInfo.cpp
+++ b/clang/lib/Format/NumericLiteralInfo.cpp
@@ -61,7 +61,8 @@ NumericLiteralInfo::NumericLiteralInfo(StringRef Text, char 
Separator) {
         return (HasExponent || !IsHex ? isDigit : isHexDigit)(C) ||
                C == Separator;
       },
-      std::min(HasExponent ? ExponentLetterPos + 2 : Pos, Text.size())); // 
e.g. 1e-2f
+      std::min(HasExponent ? ExponentLetterPos + 2 : Pos,
+               Text.size())); // e.g. 1e-2f
 }
 
 } // namespace format

From ba351b6478c32432ca1f27165af25350621ebc41 Mon Sep 17 00:00:00 2001
From: LeGusto <[email protected]>
Date: Wed, 1 Jul 2026 16:06:01 +0300
Subject: [PATCH 5/5] moved Info tests to correct location

---
 clang/lib/Format/NumericLiteralInfo.cpp           |  3 +--
 clang/unittests/Format/NumericLiteralCaseTest.cpp | 11 -----------
 clang/unittests/Format/NumericLiteralInfoTest.cpp |  8 ++++++++
 3 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/clang/lib/Format/NumericLiteralInfo.cpp 
b/clang/lib/Format/NumericLiteralInfo.cpp
index b4d0873cdc243..5738193c7cc53 100644
--- a/clang/lib/Format/NumericLiteralInfo.cpp
+++ b/clang/lib/Format/NumericLiteralInfo.cpp
@@ -61,8 +61,7 @@ NumericLiteralInfo::NumericLiteralInfo(StringRef Text, char 
Separator) {
         return (HasExponent || !IsHex ? isDigit : isHexDigit)(C) ||
                C == Separator;
       },
-      std::min(HasExponent ? ExponentLetterPos + 2 : Pos,
-               Text.size())); // e.g. 1e-2f
+      std::min(HasExponent ? ExponentLetterPos + 2 : Pos, Text.size())); // 
e.g. 1e-2f
 }
 
 } // namespace format
diff --git a/clang/unittests/Format/NumericLiteralCaseTest.cpp 
b/clang/unittests/Format/NumericLiteralCaseTest.cpp
index afb321d8d1b14..ecd230d73f692 100644
--- a/clang/unittests/Format/NumericLiteralCaseTest.cpp
+++ b/clang/unittests/Format/NumericLiteralCaseTest.cpp
@@ -340,17 +340,6 @@ TEST_F(NumericLiteralCaseTest, 
UnderScoreSeparatorLanguages) {
   verifyFormat("o = 0o0_10_010;", "o = 0O0_10_010;", Style);
 }
 
-TEST_F(NumericLiteralCaseTest, IncompleteLiteralDoesNotCrash) {
-  auto Style = getLLVMStyle();
-  Style.NumericLiteralCase.HexDigit = FormatStyle::NLCS_Upper;
-
-  verifyFormat("i = 1e;", Style);
-  verifyFormat("i = 1.0e;", Style);
-  verifyFormat("i = 0x1p;", Style);
-  verifyFormat("i = 0x;", Style);
-  verifyFormat("i = 0x_;", Style);
-}
-
 } // namespace
 } // namespace test
 } // namespace format
diff --git a/clang/unittests/Format/NumericLiteralInfoTest.cpp 
b/clang/unittests/Format/NumericLiteralInfoTest.cpp
index a892cfff531e3..018123ff5ab77 100644
--- a/clang/unittests/Format/NumericLiteralInfoTest.cpp
+++ b/clang/unittests/Format/NumericLiteralInfoTest.cpp
@@ -66,6 +66,14 @@ TEST_F(NumericLiteralInfoTest, FloatingPointLiteral) {
   EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0xF.Fp-9_Pa"), 1, 3, 5, 8));
 }
 
+TEST_F(NumericLiteralInfoTest, InvalidNumericLiteral) {
+  EXPECT_TRUE(verifyInfo(NumericLiteralInfo("1e"), npos, npos, 1, npos));
+  EXPECT_TRUE(verifyInfo(NumericLiteralInfo("1.0e"), npos, 1, 3, npos));
+  EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0x"), 1, npos, npos, npos));
+  EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0x_"), 1, npos, npos, npos));
+  EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0x1p"), 1, npos, 3, npos));
+}
+
 } // namespace
 } // namespace format
 } // namespace clang

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

Reply via email to