https://github.com/AZero13 updated https://github.com/llvm/llvm-project/pull/221102
>From 536b616a3df156247daa1db7e10d19c83f8584fc Mon Sep 17 00:00:00 2001 From: AZero13 <[email protected]> Date: Thu, 3 Sep 2026 19:44:13 -0400 Subject: [PATCH] [Clang][Parse] Fix heap-use-after-free when cleaning up TemplateIds When parsing deeply nested statement expressions, the preprocessor may exit caching mode while the parser's current token is still an `annot_template_id`. When `MaybeDestroyTemplateIds()` runs at the end of a statement, it aggressively destroyed all template ID annotations because caching mode was off. This left the current token holding a dangling pointer to a freed `TemplateIdAnnotation`, causing a crash during error recovery when extracting the `TemplateNameLoc`. This patch adds a check to ensure we don't destroy `TemplateIds` if the parser is actively holding onto an `annot_template_id` in `Tok`. Fixes #175702 --- clang/include/clang/Lex/Preprocessor.h | 6 +- .../cxx-template-id-tentative-uaf-crash.cpp | 81 +++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 clang/test/Parser/cxx-template-id-tentative-uaf-crash.cpp diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index d94f3d2cbe8ed..c1c4e84771dcf 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -2051,9 +2051,11 @@ class Preprocessor { void *AnnotationVal); /// Determine whether it's possible for a future call to Lex to produce an - /// annotation token created by a previous call to EnterAnnotationToken. + /// annotation token created by a previous call to EnterAnnotationToken, + /// or if the parser is currently holding an annotation token that was just + /// retrieved from the cache. bool mightHavePendingAnnotationTokens() { - return CurLexerCallback != CLK_Lexer; + return CurLexerCallback != CLK_Lexer || !CachedTokens.empty(); } /// Update the current token to represent the provided diff --git a/clang/test/Parser/cxx-template-id-tentative-uaf-crash.cpp b/clang/test/Parser/cxx-template-id-tentative-uaf-crash.cpp new file mode 100644 index 0000000000000..3e7d309c7d312 --- /dev/null +++ b/clang/test/Parser/cxx-template-id-tentative-uaf-crash.cpp @@ -0,0 +1,81 @@ +// RUN: not %clang_cc1 -fsyntax-only -Wno-everything %s + + +int main() { + typedef struct tree_el node i, sum = 0; + for (i = 1; i <= LAST; i++) { + sum += i; + } + printf("sum = %d\n", sum); + return printout(printf(printf( + i < cnt, cnt & (printout(printf(printf( + i < cnt, + 0x5b * printf(i < cnt, + 0x5b * (({ cnt & (printf(printf( + i < cnt, + 0x5b * (1 / (1 / (cnt & (printout( + printf(i < cnt, 0x5b * (1 / (({ + if ("%f%f%f") + break; + -((0.0 / (0xaf >> 3 & + (((0xaf >> 3 & + (({ for (i = 0, bi = i < 10; i < length; + ++i, ++bi) + if (cnt < (0xaf >> 3 & 1) >> 3) + break; + cnt < (0xaf >> 3 & 1) >> 3; + }))) + >> 0xb9 & 1) + >> 0xb9 & 1))))) + ; + }))) + ) >> + 3 & + 1))) + )))) >> + 3 & + 1))) + ) >> + 3 & + 1); + return 0; + i; + return (node())->val; +}))) + ))), + sum) >> + 3 & + 1); + return ((((({ cnt & (printf(printf( + i < cnt, + 0x5b * (({ cnt & (printf(printf( + i < cnt, + 0x5b * (1 / (1 / (cnt & (printout( + printf(i < cnt, 0x5b * (1 / (({ + if ("%f%f%f") + break; + -((0.0 / (0xaf >> 3 & + (((0xaf >> 3 & + (({ for (i = 0, bi = i < 10; i < length; ++i, ++bi) + if (cnt < (0xaf >> 3 & 1) >> 3) + break; + cnt < (0xaf >> 3 & 1) >> 3; + }))) + >> 0xb9 & 1) + >> 0xb9 & 1))))) + ; + }))) + ) >> + 3 & + 1))) + )))) >> + 3 & + 1))) + ) >> + 3 & + 1))) + , + sum)) >> + 3 & + 1))); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
