From ea310a6bb8dc229180370321235697df27569595 Mon Sep 17 00:00:00 2001 From: Alexander Kornienko Date: Sat, 27 Sep 2025 01:57:15 +0000 Subject: [PATCH 1/2] [clang] Fix a use-after free in ASTContext::getSubstBuiltinTemplatePack ASTContext::getSubstBuiltinTemplatePack finds InsertPos and then calls itself recursively, which may lead to rehashing and invalidation of all pointers to buckets. The function then proceeds with using the potentially invalid InsertPos, leading to use-after-free. I didn't manage to produce a reasonably-sized test case yet. --- clang/lib/AST/ASTContext.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 07d42e7e2f3b3..e9d3e58f81cf2 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5873,8 +5873,14 @@ ASTContext::getSubstBuiltinTemplatePack(const TemplateArgument &ArgPack) { QualType Canon; TemplateArgument CanonArgPack = getCanonicalTemplateArgument(ArgPack); - if (!CanonArgPack.structurallyEquals(ArgPack)) + if (!CanonArgPack.structurallyEquals(ArgPack)) { Canon = getSubstBuiltinTemplatePack(CanonArgPack); + // Refresh InsertPos, in case the recursive call above caused rehashing, + // which would invalidate the bucket pointer. + if (auto *T = + SubstBuiltinTemplatePackTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(T, 0); + } auto *PackType = new (*this, alignof(SubstBuiltinTemplatePackType)) SubstBuiltinTemplatePackType(Canon, ArgPack); From edff46e51b18aacf0ba827b76232e1e4e32ced10 Mon Sep 17 00:00:00 2001 From: Alexander Kornienko Date: Sat, 27 Sep 2025 02:24:03 +0000 Subject: [PATCH 2/2] Address review comments. Assert that a node is not found when refreshing InsertPos. --- clang/lib/AST/ASTContext.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index e9d3e58f81cf2..61dd330553860 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5877,9 +5877,9 @@ ASTContext::getSubstBuiltinTemplatePack(const TemplateArgument &ArgPack) { Canon = getSubstBuiltinTemplatePack(CanonArgPack); // Refresh InsertPos, in case the recursive call above caused rehashing, // which would invalidate the bucket pointer. - if (auto *T = - SubstBuiltinTemplatePackTypes.FindNodeOrInsertPos(ID, InsertPos)) - return QualType(T, 0); + [[maybe_unused]] const auto *Nothing = + SubstBuiltinTemplatePackTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!Nothing); } auto *PackType = new (*this, alignof(SubstBuiltinTemplatePackType))