Skip to content

Commit b093188

Browse files
committed
Fix use-after-free in SwiftLanguageRuntimeImpl::GetChildCompilerTypeAtIndex()
This function broke the contract with ForEachSuperClass by making a copy of the returned super classes and then calling into the callbacks outside of the closure. rdar://87565969 (cherry picked from commit 3e2bc96)
1 parent 6d9ce4e commit b093188

File tree

2 files changed

+30
-16
lines changed

2 files changed

+30
-16
lines changed

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,22 +1574,36 @@ CompilerType SwiftLanguageRuntimeImpl::GetChildCompilerTypeAtIndex(
15741574
NodePointer type_node = dem.demangleSymbol(mangled);
15751575
llvm::StringRef type_name = TypeSystemSwiftTypeRef::GetBaseName(
15761576
ts->CanonicalizeSugar(dem, type_node));
1577+
1578+
auto *reflection_ctx = GetReflectionContext();
1579+
if (!reflection_ctx)
1580+
return {};
1581+
CompilerType instance_type = valobj->GetCompilerType();
1582+
auto *instance_ts =
1583+
llvm::dyn_cast_or_null<TypeSystemSwift>(instance_type.GetTypeSystem());
1584+
if (!instance_ts)
1585+
return {};
1586+
1587+
// LLDBTypeInfoProvider needs to kept alive until as long as supers gets accessed.
15771588
llvm::SmallVector<SuperClassType, 2> supers;
1578-
ForEachSuperClassType(*valobj, [&](SuperClassType sc) -> bool {
1579-
if (!found_start) {
1580-
// The ValueObject always points to the same class instance,
1581-
// even when querying base classes. Drop base classes until we
1582-
// reach the requested type.
1583-
if (auto *tr = sc.get_typeref()) {
1584-
NodePointer base_class = tr->getDemangling(dem);
1585-
if (TypeSystemSwiftTypeRef::GetBaseName(base_class) != type_name)
1586-
return false;
1587-
found_start = true;
1588-
}
1589-
}
1590-
supers.push_back(sc);
1591-
return supers.size() >= 2;
1592-
});
1589+
LLDBTypeInfoProvider tip(*this, *instance_ts);
1590+
lldb::addr_t pointer = valobj->GetPointerValue();
1591+
reflection_ctx->ForEachSuperClassType(
1592+
&tip, pointer, [&](SuperClassType sc) -> bool {
1593+
if (!found_start) {
1594+
// The ValueObject always points to the same class instance,
1595+
// even when querying base classes. Drop base classes until we
1596+
// reach the requested type.
1597+
if (auto *tr = sc.get_typeref()) {
1598+
NodePointer base_class = tr->getDemangling(dem);
1599+
if (TypeSystemSwiftTypeRef::GetBaseName(base_class) != type_name)
1600+
return false;
1601+
found_start = true;
1602+
}
1603+
}
1604+
supers.push_back(sc);
1605+
return supers.size() >= 2;
1606+
});
15931607

15941608
if (supers.size() == 0) {
15951609
LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES),

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ class SwiftLanguageRuntimeImpl {
247247
/// If \p instance points to a Swift object, retrieve its
248248
/// RecordTypeInfo and pass it to the callback \p fn. Repeat the
249249
/// process with all superclasses. If \p fn returns \p true, early
250-
/// exit and return \ptrue. Otherwise return \p false.
250+
/// exit and return \p true. Otherwise return \p false.
251251
bool ForEachSuperClassType(ValueObject &instance,
252252
std::function<bool(SuperClassType)> fn);
253253

0 commit comments

Comments
 (0)