Author: Jonas Devlieghere
Date: 2025-06-24T12:28:40-07:00
New Revision: b171ebbfffcd4b8d923734dd0fc077b02a6fe3f7

URL: 
https://github.com/llvm/llvm-project/commit/b171ebbfffcd4b8d923734dd0fc077b02a6fe3f7
DIFF: 
https://github.com/llvm/llvm-project/commit/b171ebbfffcd4b8d923734dd0fc077b02a6fe3f7.diff

LOG: [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

Added: 
    

Modified: 
    
lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
    
lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h

Removed: 
    


################################################################################
diff  --git 
a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
 
b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index e459cb281793a..4fcdebe5bac62 100644
--- 
a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ 
b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -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

diff  --git 
a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
 
b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
index 79840f9be79b3..b99bda2f7e259 100644
--- 
a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
+++ 
b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
@@ -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 @@ class AppleObjCRuntimeV2 : public AppleObjCRuntime {
 
   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


        
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to