Skip to content

[lldb] Refactor away UB in SBValue::GetLoadAddress #141799

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 2, 2025
Merged

Conversation

labath
Copy link
Collaborator

@labath labath commented May 28, 2025

The problem was in calling GetLoadAddress on a value in the error state, where ValueObject::GetLoadAddress could end up accessing the uninitialized "address type" by-ref return value from GetAddressOf. This probably happened because each function expected the other to initialize it.

We can guarantee initialization by turning this into a proper return value.

I've added a test, but it only (reliably) crashes if lldb is built with ubsan.

@labath labath requested a review from jimingham May 28, 2025 16:34
@labath labath requested a review from JDevlieghere as a code owner May 28, 2025 16:34
@llvmbot llvmbot added the lldb label May 28, 2025
@llvmbot
Copy link
Member

llvmbot commented May 28, 2025

@llvm/pr-subscribers-lldb

Author: Pavel Labath (labath)

Changes

The problem was in calling GetLoadAddress on a value in the error state, where ValueObject::GetLoadAddress could end up accessing the uninitialized "address type" by-ref return value from GetAddressOf. This probably happened because each function expected the other to initialize it.

We can guarantee initialization by turning this into a proper return value.

I've added a test, but it only (reliably) crashes if lldb is built with ubsan.


Patch is 34.79 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/141799.diff

26 Files Affected:

  • (modified) lldb/include/lldb/ValueObject/ValueObject.h (+3-3)
  • (modified) lldb/include/lldb/ValueObject/ValueObjectConstResult.h (+2-2)
  • (modified) lldb/include/lldb/ValueObject/ValueObjectConstResultChild.h (+2-2)
  • (modified) lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h (+2-2)
  • (modified) lldb/source/API/SBValue.cpp (+2-4)
  • (modified) lldb/source/Commands/CommandObjectWatchpoint.cpp (+1-1)
  • (modified) lldb/source/DataFormatters/CXXFunctionPointer.cpp (+1-2)
  • (modified) lldb/source/DataFormatters/FormattersHelpers.cpp (+5-3)
  • (modified) lldb/source/DataFormatters/TypeFormat.cpp (+1-1)
  • (modified) lldb/source/DataFormatters/ValueObjectPrinter.cpp (+1-2)
  • (modified) lldb/source/Expression/Materializer.cpp (+1-3)
  • (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp (+1-1)
  • (modified) lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp (+1-2)
  • (modified) lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp (+1-1)
  • (modified) lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp (+5-13)
  • (modified) lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp (+30-36)
  • (modified) lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp (+1-1)
  • (modified) lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (+2-2)
  • (modified) lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp (+1-1)
  • (modified) lldb/source/ValueObject/ValueObject.cpp (+35-58)
  • (modified) lldb/source/ValueObject/ValueObjectChild.cpp (+1-1)
  • (modified) lldb/source/ValueObject/ValueObjectConstResult.cpp (+3-3)
  • (modified) lldb/source/ValueObject/ValueObjectConstResultChild.cpp (+3-4)
  • (modified) lldb/source/ValueObject/ValueObjectConstResultImpl.cpp (+6-12)
  • (modified) lldb/source/ValueObject/ValueObjectVTable.cpp (+1-1)
  • (modified) lldb/test/API/python_api/value/TestValueAPI.py (+9-4)
diff --git a/lldb/include/lldb/ValueObject/ValueObject.h b/lldb/include/lldb/ValueObject/ValueObject.h
index 0add8ebeccdc8..5b78e57cb4996 100644
--- a/lldb/include/lldb/ValueObject/ValueObject.h
+++ b/lldb/include/lldb/ValueObject/ValueObject.h
@@ -573,10 +573,10 @@ class ValueObject {
   /// child as well.
   void SetName(ConstString name) { m_name = name; }
 
-  virtual lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
-                                    AddressType *address_type = nullptr);
+  virtual std::pair<AddressType, lldb::addr_t>
+  GetAddressOf(bool scalar_is_load_address = true);
 
-  lldb::addr_t GetPointerValue(AddressType *address_type = nullptr);
+  std::pair<AddressType, lldb::addr_t> GetPointerValue();
 
   lldb::ValueObjectSP GetSyntheticChild(ConstString key) const;
 
diff --git a/lldb/include/lldb/ValueObject/ValueObjectConstResult.h b/lldb/include/lldb/ValueObject/ValueObjectConstResult.h
index 2ee531f5858e1..3a11ab360649a 100644
--- a/lldb/include/lldb/ValueObject/ValueObjectConstResult.h
+++ b/lldb/include/lldb/ValueObject/ValueObjectConstResult.h
@@ -86,8 +86,8 @@ class ValueObjectConstResult : public ValueObject {
 
   lldb::ValueObjectSP AddressOf(Status &error) override;
 
-  lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
-                            AddressType *address_type = nullptr) override;
+  std::pair<AddressType, lldb::addr_t>
+  GetAddressOf(bool scalar_is_load_address = true) override;
 
   size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
                         uint32_t item_count = 1) override;
diff --git a/lldb/include/lldb/ValueObject/ValueObjectConstResultChild.h b/lldb/include/lldb/ValueObject/ValueObjectConstResultChild.h
index ad97b885684ee..09d62253e1bb0 100644
--- a/lldb/include/lldb/ValueObject/ValueObjectConstResultChild.h
+++ b/lldb/include/lldb/ValueObject/ValueObjectConstResultChild.h
@@ -48,8 +48,8 @@ class ValueObjectConstResultChild : public ValueObjectChild {
 
   lldb::ValueObjectSP AddressOf(Status &error) override;
 
-  lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
-                            AddressType *address_type = nullptr) override;
+  std::pair<AddressType, lldb::addr_t>
+  GetAddressOf(bool scalar_is_load_address = true) override;
 
   size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
                         uint32_t item_count = 1) override;
diff --git a/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h b/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h
index 5509886a8965d..3fc882ac782ec 100644
--- a/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h
+++ b/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h
@@ -58,8 +58,8 @@ class ValueObjectConstResultImpl {
     m_live_address_type = address_type;
   }
 
-  virtual lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
-                                    AddressType *address_type = nullptr);
+  virtual std::pair<AddressType, lldb::addr_t>
+  GetAddressOf(bool scalar_is_load_address = true);
 
   virtual size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
                                 uint32_t item_count = 1);
diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp
index 88c86a5482910..4b7aae6a54a04 100644
--- a/lldb/source/API/SBValue.cpp
+++ b/lldb/source/API/SBValue.cpp
@@ -1336,10 +1336,8 @@ lldb::SBAddress SBValue::GetAddress() {
   if (value_sp) {
     TargetSP target_sp(value_sp->GetTargetSP());
     if (target_sp) {
-      lldb::addr_t value = LLDB_INVALID_ADDRESS;
-      const bool scalar_is_load_address = true;
-      AddressType addr_type;
-      value = value_sp->GetAddressOf(scalar_is_load_address, &addr_type);
+      auto [addr_type, value] =
+          value_sp->GetAddressOf(/*scalar_is_load_address=*/true);
       if (addr_type == eAddressTypeFile) {
         ModuleSP module_sp(value_sp->GetModule());
         if (module_sp)
diff --git a/lldb/source/Commands/CommandObjectWatchpoint.cpp b/lldb/source/Commands/CommandObjectWatchpoint.cpp
index 20f4b91f15340..e36c6a33de7df 100644
--- a/lldb/source/Commands/CommandObjectWatchpoint.cpp
+++ b/lldb/source/Commands/CommandObjectWatchpoint.cpp
@@ -863,7 +863,7 @@ corresponding to the byte size of the data type.");
 
     if (valobj_sp) {
       AddressType addr_type;
-      addr = valobj_sp->GetAddressOf(false, &addr_type);
+      std::tie(addr_type, addr) = valobj_sp->GetAddressOf(false);
       if (addr_type == eAddressTypeLoad) {
         // We're in business.
         // Find out the size of this variable.
diff --git a/lldb/source/DataFormatters/CXXFunctionPointer.cpp b/lldb/source/DataFormatters/CXXFunctionPointer.cpp
index d79fb1d678ebd..7e73086ee6a35 100644
--- a/lldb/source/DataFormatters/CXXFunctionPointer.cpp
+++ b/lldb/source/DataFormatters/CXXFunctionPointer.cpp
@@ -24,8 +24,7 @@ using namespace lldb_private::formatters;
 bool lldb_private::formatters::CXXFunctionPointerSummaryProvider(
     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
   StreamString sstr;
-  AddressType func_ptr_address_type = eAddressTypeInvalid;
-  addr_t func_ptr_address = valobj.GetPointerValue(&func_ptr_address_type);
+  auto [func_ptr_address_type, func_ptr_address] = valobj.GetPointerValue();
   if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) {
     switch (func_ptr_address_type) {
     case eAddressTypeInvalid:
diff --git a/lldb/source/DataFormatters/FormattersHelpers.cpp b/lldb/source/DataFormatters/FormattersHelpers.cpp
index 5f5541c352623..38cee43a64471 100644
--- a/lldb/source/DataFormatters/FormattersHelpers.cpp
+++ b/lldb/source/DataFormatters/FormattersHelpers.cpp
@@ -114,12 +114,14 @@ lldb_private::formatters::ExtractIndexFromString(const char *item_name) {
 Address
 lldb_private::formatters::GetArrayAddressOrPointerValue(ValueObject &valobj) {
   lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
-  AddressType type;
+  AddressType type = eAddressTypeInvalid;
 
   if (valobj.IsPointerType())
-    data_addr = valobj.GetPointerValue(&type);
+    std::tie(type, data_addr) = valobj.GetPointerValue();
   else if (valobj.IsArrayType())
-    data_addr = valobj.GetAddressOf(/*scalar_is_load_address=*/true, &type);
+    std::tie(type, data_addr) =
+        valobj.GetAddressOf(/*scalar_is_load_address=*/true);
+
   if (data_addr != LLDB_INVALID_ADDRESS && type == eAddressTypeFile)
     return Address(data_addr, valobj.GetModule()->GetSectionList());
 
diff --git a/lldb/source/DataFormatters/TypeFormat.cpp b/lldb/source/DataFormatters/TypeFormat.cpp
index f4cb8b46d272a..6b91a76f9d9c5 100644
--- a/lldb/source/DataFormatters/TypeFormat.cpp
+++ b/lldb/source/DataFormatters/TypeFormat.cpp
@@ -80,7 +80,7 @@ bool TypeFormatImpl_Format::FormatObject(ValueObject *valobj,
               Status error;
               WritableDataBufferSP buffer_sp(
                   new DataBufferHeap(max_len + 1, 0));
-              Address address(valobj->GetPointerValue());
+              Address address(valobj->GetPointerValue().second);
               target_sp->ReadCStringFromMemory(
                   address, (char *)buffer_sp->GetBytes(), max_len, error);
               if (error.Success())
diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
index 5e04a621bbda8..0d6af406012a3 100644
--- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp
+++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
@@ -542,8 +542,7 @@ bool ValueObjectPrinter::ShouldPrintChildren(
   if (is_ptr || is_ref) {
     // We have a pointer or reference whose value is an address. Make sure
     // that address is not NULL
-    AddressType ptr_address_type;
-    if (valobj.GetPointerValue(&ptr_address_type) == 0)
+    if (valobj.GetPointerValue().second == 0)
       return false;
 
     const bool is_root_level = m_curr_depth == 0;
diff --git a/lldb/source/Expression/Materializer.cpp b/lldb/source/Expression/Materializer.cpp
index 8d48b5e50041c..634b929ce19a1 100644
--- a/lldb/source/Expression/Materializer.cpp
+++ b/lldb/source/Expression/Materializer.cpp
@@ -508,10 +508,8 @@ class EntityVariableBase : public Materializer::Entity {
         return;
       }
     } else {
-      AddressType address_type = eAddressTypeInvalid;
-      const bool scalar_is_load_address = false;
       lldb::addr_t addr_of_valobj =
-          valobj_sp->GetAddressOf(scalar_is_load_address, &address_type);
+          valobj_sp->GetAddressOf(/*scalar_is_load_address=*/false).second;
       if (addr_of_valobj != LLDB_INVALID_ADDRESS) {
         Status write_error;
         map.WritePointerToMemory(load_addr, addr_of_valobj, write_error);
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
index ae34a983612f7..fad21d5b1275e 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -898,7 +898,7 @@ bool ClangUserExpression::AddArguments(ExecutionContext &exe_ctx,
 
     if (m_ctx_obj) {
       AddressType address_type;
-      object_ptr = m_ctx_obj->GetAddressOf(false, &address_type);
+      std::tie(address_type, object_ptr) = m_ctx_obj->GetAddressOf(false);
       if (object_ptr == LLDB_INVALID_ADDRESS ||
           address_type != eAddressTypeLoad)
         object_ptr_error = Status::FromErrorString("Can't get context object's "
diff --git a/lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp b/lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp
index d3cdb231fbb01..8e01878eec6b0 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp
@@ -32,8 +32,7 @@ static lldb::addr_t GetCoroFramePtrFromHandle(ValueObjectSP valobj_sp) {
   if (!ptr_sp->GetCompilerType().IsPointerType())
     return LLDB_INVALID_ADDRESS;
 
-  AddressType addr_type;
-  lldb::addr_t frame_ptr_addr = ptr_sp->GetPointerValue(&addr_type);
+  auto [addr_type, frame_ptr_addr] = ptr_sp->GetPointerValue();
   if (!frame_ptr_addr || frame_ptr_addr == LLDB_INVALID_ADDRESS)
     return LLDB_INVALID_ADDRESS;
   lldbassert(addr_type == AddressType::eAddressTypeLoad);
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
index 30db5f15c388f..851fe821408c5 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
@@ -388,7 +388,7 @@ lldb::ValueObjectSP ListFrontEnd::GetChildAtIndex(uint32_t idx) {
       return lldb::ValueObjectSP();
 
     // if we grabbed the __next_ pointer, then the child is one pointer deep-er
-    lldb::addr_t addr = current_sp->GetParent()->GetPointerValue();
+    lldb::addr_t addr = current_sp->GetParent()->GetPointerValue().second;
     addr = addr + 2 * process_sp->GetAddressByteSize();
     ExecutionContext exe_ctx(process_sp);
     current_sp =
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
index 02113baf64b8c..b00b7cc1c2681 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
@@ -240,16 +240,10 @@ VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName(ConstString name) {
 bool lldb_private::formatters::LibStdcppStringSummaryProvider(
     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
   const bool scalar_is_load_addr = true;
-  AddressType addr_type;
-  lldb::addr_t addr_of_string = LLDB_INVALID_ADDRESS;
-  if (valobj.IsPointerOrReferenceType()) {
-    Status error;
-    ValueObjectSP pointee_sp = valobj.Dereference(error);
-    if (pointee_sp && error.Success())
-      addr_of_string = pointee_sp->GetAddressOf(scalar_is_load_addr, &addr_type);
-  } else
-    addr_of_string =
-        valobj.GetAddressOf(scalar_is_load_addr, &addr_type);
+  auto [addr_type, addr_of_string] =
+      valobj.IsPointerOrReferenceType()
+          ? valobj.GetPointerValue()
+          : valobj.GetAddressOf(scalar_is_load_addr);
   if (addr_of_string != LLDB_INVALID_ADDRESS) {
     switch (addr_type) {
     case eAddressTypeLoad: {
@@ -296,9 +290,7 @@ bool lldb_private::formatters::LibStdcppStringSummaryProvider(
 bool lldb_private::formatters::LibStdcppWStringSummaryProvider(
     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
   const bool scalar_is_load_addr = true;
-  AddressType addr_type;
-  lldb::addr_t addr_of_string =
-      valobj.GetAddressOf(scalar_is_load_addr, &addr_type);
+  auto [addr_type, addr_of_string] = valobj.GetAddressOf(scalar_is_load_addr);
   if (addr_of_string != LLDB_INVALID_ADDRESS) {
     switch (addr_type) {
     case eAddressTypeLoad: {
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index 0d068ed5950d5..2ee0d0dff824f 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -69,9 +69,8 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfo(
       LLDB_LOGF(log,
                 "0x%16.16" PRIx64
                 ": static-type = '%s' has vtable symbol '%s'\n",
-                in_value.GetPointerValue(),
-                in_value.GetTypeName().GetCString(),
-                symbol_name.str().c_str());
+                in_value.GetPointerValue().second,
+                in_value.GetTypeName().GetCString(), symbol_name.str().c_str());
       // We are a C++ class, that's good.  Get the class name and look it
       // up:
       llvm::StringRef class_name = symbol_name;
@@ -111,7 +110,7 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfo(
       lldb::TypeSP type_sp;
       if (class_types.Empty()) {
         LLDB_LOGF(log, "0x%16.16" PRIx64 ": is not dynamic\n",
-                  in_value.GetPointerValue());
+                  in_value.GetPointerValue().second);
         return TypeAndOrName();
       }
       if (class_types.GetSize() == 1) {
@@ -119,13 +118,13 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfo(
         if (type_sp) {
           if (TypeSystemClang::IsCXXClassType(
                   type_sp->GetForwardCompilerType())) {
-            LLDB_LOGF(
-                log,
-                "0x%16.16" PRIx64
-                ": static-type = '%s' has dynamic type: uid={0x%" PRIx64
-                "}, type-name='%s'\n",
-                in_value.GetPointerValue(), in_value.GetTypeName().AsCString(),
-                type_sp->GetID(), type_sp->GetName().GetCString());
+            LLDB_LOGF(log,
+                      "0x%16.16" PRIx64
+                      ": static-type = '%s' has dynamic type: uid={0x%" PRIx64
+                      "}, type-name='%s'\n",
+                      in_value.GetPointerValue().second,
+                      in_value.GetTypeName().AsCString(), type_sp->GetID(),
+                      type_sp->GetName().GetCString());
             type_info.SetTypeSP(type_sp);
           }
         }
@@ -135,14 +134,13 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfo(
           for (i = 0; i < class_types.GetSize(); i++) {
             type_sp = class_types.GetTypeAtIndex(i);
             if (type_sp) {
-              LLDB_LOGF(
-                  log,
-                  "0x%16.16" PRIx64
-                  ": static-type = '%s' has multiple matching dynamic "
-                  "types: uid={0x%" PRIx64 "}, type-name='%s'\n",
-                  in_value.GetPointerValue(),
-                  in_value.GetTypeName().AsCString(),
-                  type_sp->GetID(), type_sp->GetName().GetCString());
+              LLDB_LOGF(log,
+                        "0x%16.16" PRIx64
+                        ": static-type = '%s' has multiple matching dynamic "
+                        "types: uid={0x%" PRIx64 "}, type-name='%s'\n",
+                        in_value.GetPointerValue().second,
+                        in_value.GetTypeName().AsCString(), type_sp->GetID(),
+                        type_sp->GetName().GetCString());
             }
           }
         }
@@ -152,14 +150,13 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfo(
           if (type_sp) {
             if (TypeSystemClang::IsCXXClassType(
                     type_sp->GetForwardCompilerType())) {
-              LLDB_LOGF(
-                  log,
-                  "0x%16.16" PRIx64 ": static-type = '%s' has multiple "
-                  "matching dynamic types, picking "
-                  "this one: uid={0x%" PRIx64 "}, type-name='%s'\n",
-                  in_value.GetPointerValue(),
-                  in_value.GetTypeName().AsCString(),
-                  type_sp->GetID(), type_sp->GetName().GetCString());
+              LLDB_LOGF(log,
+                        "0x%16.16" PRIx64 ": static-type = '%s' has multiple "
+                        "matching dynamic types, picking "
+                        "this one: uid={0x%" PRIx64 "}, type-name='%s'\n",
+                        in_value.GetPointerValue().second,
+                        in_value.GetTypeName().AsCString(), type_sp->GetID(),
+                        type_sp->GetName().GetCString());
               type_info.SetTypeSP(type_sp);
             }
           }
@@ -170,7 +167,7 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfo(
                     "0x%16.16" PRIx64
                     ": static-type = '%s' has multiple matching dynamic "
                     "types, didn't find a C++ match\n",
-                    in_value.GetPointerValue(),
+                    in_value.GetPointerValue().second,
                     in_value.GetTypeName().AsCString());
         }
       }
@@ -230,13 +227,10 @@ llvm::Expected<LanguageRuntime::VTableInfo>
     return llvm::createStringError(std::errc::invalid_argument,
                                    "invalid process");
 
-  AddressType address_type;
-  lldb::addr_t original_ptr = LLDB_INVALID_ADDRESS;
-  if (type.IsPointerOrReferenceType())
-    original_ptr = in_value.GetPointerValue(&address_type);
-  else
-    original_ptr = in_value.GetAddressOf(/*scalar_is_load_address=*/true,
-                                         &address_type);
+  auto [address_type, original_ptr] =
+      type.IsPointerOrReferenceType()
+          ? in_value.GetPointerValue()
+          : in_value.GetAddressOf(/*scalar_is_load_address=*/true);
   if (original_ptr == LLDB_INVALID_ADDRESS || address_type != eAddressTypeLoad)
     return llvm::createStringError(std::errc::invalid_argument,
                                    "failed to get the address of the value");
@@ -357,7 +351,7 @@ bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress(
     return false;
   // So the dynamic type is a value that starts at offset_to_top above
   // the original address.
-  lldb::addr_t dynamic_addr = in_value.GetPointerValue() + offset_to_top;
+  lldb::addr_t dynamic_addr = in_value.GetPointerValue().second + offset_to_top;
   if (!m_process->GetTarget().ResolveLoadAddress(
           dynamic_addr, dynamic_address)) {
     dynamic_address.SetRawAddress(dynamic_addr);
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
index db1317d70d060..2e31a3c645a78 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
@@ -55,7 +55,7 @@ bool AppleObjCRuntimeV1::GetDynamicTypeAndAddress(
     auto class_descriptor(GetClassDescriptor(in_value));
     if (class_descriptor && class_descriptor->IsValid() &&
         class_descriptor->GetClassName()) {
-      const addr_t object_ptr = in_value.GetPointerValue();
+      const addr_t object_ptr = in_value.GetPointerValue().second;
       address.SetRawAddress(object_ptr);
       class_type_or_name.SetName(class_descriptor->GetClassName());
     }
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index...
[truncated]

Copy link

github-actions bot commented May 28, 2025

✅ With the latest revision this PR passed the Python code formatter.

The problem was in calling GetLoadAddress on a value in the error state,
where `ValueObject::GetLoadAddress` could end up accessing the
uninitialized "address type" by-ref return value from `GetAddressOf`.
This probably happened because each function expected the other to
initialize it.

We can guarantee initialization by turning this into a proper return
value.

I've added a test, but it only (reliably) crashes if lldb is built with
ubsan.
@jimingham
Copy link
Collaborator

It always makes me a little sad to see .first or .second showing up - they are so non-self-documenting. How horrible would this be if you used a struct AddrAndType { AddressType type; lldb::addr_t address} (I'm a bit surprised we don't have one already) instead so that you would do GetLoadAddress().address rather than GetLoadAddress().second?

@labath
Copy link
Collaborator Author

labath commented May 29, 2025

Using a named struct now. I think it worked out pretty well. One thing you can't do (without additional goo) with this struct is to use std::tie to decompose it, but I think I managed to refactor stuff so that this is not needed.

Copy link
Collaborator

@jimingham jimingham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That worked out pretty well.

@labath labath merged commit e9fad0e into llvm:main Jun 2, 2025
10 checks passed
@labath labath deleted the addrof branch June 2, 2025 07:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants