[clang] [clang] Fix a use-after free in ASTContext::getSubstBuiltinTemplatePack (PR #160970)
Alexander Kornienko via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 26 19:29:04 PDT 2025
https://github.com/alexfh updated https://github.com/llvm/llvm-project/pull/160970
>From ea310a6bb8dc229180370321235697df27569595 Mon Sep 17 00:00:00 2001
From: Alexander Kornienko <alexfh at google.com>
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 <alexfh at google.com>
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))
More information about the cfe-commits
mailing list