Skip to content

Commit 3e2bc96

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
1 parent 1d9bbf2 commit 3e2bc96

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
@@ -1597,22 +1597,36 @@ CompilerType SwiftLanguageRuntimeImpl::GetChildCompilerTypeAtIndex(
15971597
NodePointer type_node = dem.demangleSymbol(mangled);
15981598
llvm::StringRef type_name = TypeSystemSwiftTypeRef::GetBaseName(
15991599
ts->CanonicalizeSugar(dem, type_node));
1600+
1601+
auto *reflection_ctx = GetReflectionContext();
1602+
if (!reflection_ctx)
1603+
return {};
1604+
CompilerType instance_type = valobj->GetCompilerType();
1605+
auto *instance_ts =
1606+
llvm::dyn_cast_or_null<TypeSystemSwift>(instance_type.GetTypeSystem());
1607+
if (!instance_ts)
1608+
return {};
1609+
1610+
// LLDBTypeInfoProvider needs to kept alive until as long as supers gets accessed.
16001611
llvm::SmallVector<SuperClassType, 2> supers;
1601-
ForEachSuperClassType(*valobj, [&](SuperClassType sc) -> bool {
1602-
if (!found_start) {
1603-
// The ValueObject always points to the same class instance,
1604-
// even when querying base classes. Drop base classes until we
1605-
// reach the requested type.
1606-
if (auto *tr = sc.get_typeref()) {
1607-
NodePointer base_class = tr->getDemangling(dem);
1608-
if (TypeSystemSwiftTypeRef::GetBaseName(base_class) != type_name)
1609-
return false;
1610-
found_start = true;
1611-
}
1612-
}
1613-
supers.push_back(sc);
1614-
return supers.size() >= 2;
1615-
});
1612+
LLDBTypeInfoProvider tip(*this, *instance_ts);
1613+
lldb::addr_t pointer = valobj->GetPointerValue();
1614+
reflection_ctx->ForEachSuperClassType(
1615+
&tip, pointer, [&](SuperClassType sc) -> bool {
1616+
if (!found_start) {
1617+
// The ValueObject always points to the same class instance,
1618+
// even when querying base classes. Drop base classes until we
1619+
// reach the requested type.
1620+
if (auto *tr = sc.get_typeref()) {
1621+
NodePointer base_class = tr->getDemangling(dem);
1622+
if (TypeSystemSwiftTypeRef::GetBaseName(base_class) != type_name)
1623+
return false;
1624+
found_start = true;
1625+
}
1626+
}
1627+
supers.push_back(sc);
1628+
return supers.size() >= 2;
1629+
});
16161630

16171631
if (supers.size() == 0) {
16181632
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
@@ -246,7 +246,7 @@ class SwiftLanguageRuntimeImpl {
246246
/// If \p instance points to a Swift object, retrieve its
247247
/// RecordTypeInfo and pass it to the callback \p fn. Repeat the
248248
/// process with all superclasses. If \p fn returns \p true, early
249-
/// exit and return \ptrue. Otherwise return \p false.
249+
/// exit and return \p true. Otherwise return \p false.
250250
bool ForEachSuperClassType(ValueObject &instance,
251251
std::function<bool(SuperClassType)> fn);
252252

0 commit comments

Comments
 (0)