[lldb] Defend against infinite recursion in GetClassDescriptor (#145396)
We defend against a direct cycle where a base class ValueObject is its own parent, but not against a longer base cycle. This cycle requires that some value's Type includes a base class, and that base class is in a class hierarchy that cycles back to the original base class. I wrote a test case that creates a cycle in the class hierarchy by dynamically overwriting the superclass of an object, but I can't reproduce the crash. I can't think of any other way to make a real object that behaves that way. Maybe is a type system problem in making up the type for whatever type we're trying to ingest here. While unsatisfying, without a reproducer this is the best we can do for now. rdar://140293233
This commit is contained in:
committed by
GitHub
parent
2b5141189f
commit
b171ebbfff
@@ -1505,15 +1505,24 @@ AppleObjCRuntimeV2::GetClassDescriptorFromISA(ObjCISA isa) {
|
||||
|
||||
ObjCLanguageRuntime::ClassDescriptorSP
|
||||
AppleObjCRuntimeV2::GetClassDescriptor(ValueObject &valobj) {
|
||||
ValueObjectSet seen;
|
||||
return GetClassDescriptorImpl(valobj, seen);
|
||||
}
|
||||
|
||||
ObjCLanguageRuntime::ClassDescriptorSP
|
||||
AppleObjCRuntimeV2::GetClassDescriptorImpl(ValueObject &valobj,
|
||||
ValueObjectSet &seen) {
|
||||
seen.insert(&valobj);
|
||||
|
||||
ClassDescriptorSP objc_class_sp;
|
||||
if (valobj.IsBaseClass()) {
|
||||
ValueObject *parent = valobj.GetParent();
|
||||
// if I am my own parent, bail out of here fast..
|
||||
if (parent && parent != &valobj) {
|
||||
ClassDescriptorSP parent_descriptor_sp = GetClassDescriptor(*parent);
|
||||
if (parent_descriptor_sp)
|
||||
return parent_descriptor_sp->GetSuperclass();
|
||||
}
|
||||
// Fail if there's a cycle in our parent chain.
|
||||
if (!parent || seen.count(parent))
|
||||
return nullptr;
|
||||
if (ClassDescriptorSP parent_descriptor_sp =
|
||||
GetClassDescriptorImpl(*parent, seen))
|
||||
return parent_descriptor_sp->GetSuperclass();
|
||||
return nullptr;
|
||||
}
|
||||
// if we get an invalid VO (which might still happen when playing around with
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
|
||||
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
|
||||
class RemoteNXMapTable;
|
||||
|
||||
@@ -421,6 +422,10 @@ private:
|
||||
|
||||
lldb::addr_t GetISAHashTablePointer();
|
||||
|
||||
using ValueObjectSet = llvm::SmallPtrSet<ValueObject *, 8>;
|
||||
ClassDescriptorSP GetClassDescriptorImpl(ValueObject &valobj,
|
||||
ValueObjectSet &seen);
|
||||
|
||||
/// Update the generation count of realized classes. This is not an exact
|
||||
/// count but rather a value that is incremented when new classes are realized
|
||||
/// or destroyed. Unlike the count in gdb_objc_realized_classes, it will
|
||||
|
||||
Reference in New Issue
Block a user