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/3] [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/3] 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/3] 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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
