Skip to content

Commit e9fad0e

Browse files
authored
[lldb] Refactor away UB in SBValue::GetLoadAddress (llvm#141799)
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.
1 parent 246d5da commit e9fad0e

26 files changed

+147
-189
lines changed

lldb/include/lldb/ValueObject/ValueObject.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -573,10 +573,14 @@ class ValueObject {
573573
/// child as well.
574574
void SetName(ConstString name) { m_name = name; }
575575

576-
virtual lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
577-
AddressType *address_type = nullptr);
576+
struct AddrAndType {
577+
lldb::addr_t address = LLDB_INVALID_ADDRESS;
578+
AddressType type = eAddressTypeInvalid;
579+
};
580+
581+
virtual AddrAndType GetAddressOf(bool scalar_is_load_address = true);
578582

579-
lldb::addr_t GetPointerValue(AddressType *address_type = nullptr);
583+
AddrAndType GetPointerValue();
580584

581585
lldb::ValueObjectSP GetSyntheticChild(ConstString key) const;
582586

lldb/include/lldb/ValueObject/ValueObjectConstResult.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@ class ValueObjectConstResult : public ValueObject {
8686

8787
lldb::ValueObjectSP AddressOf(Status &error) override;
8888

89-
lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
90-
AddressType *address_type = nullptr) override;
89+
AddrAndType GetAddressOf(bool scalar_is_load_address = true) override;
9190

9291
size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
9392
uint32_t item_count = 1) override;

lldb/include/lldb/ValueObject/ValueObjectConstResultChild.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ class ValueObjectConstResultChild : public ValueObjectChild {
4848

4949
lldb::ValueObjectSP AddressOf(Status &error) override;
5050

51-
lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
52-
AddressType *address_type = nullptr) override;
51+
AddrAndType GetAddressOf(bool scalar_is_load_address = true) override;
5352

5453
size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
5554
uint32_t item_count = 1) override;

lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLDB_VALUEOBJECT_VALUEOBJECTCONSTRESULTIMPL_H
1111

1212
#include "lldb/Utility/ConstString.h"
13+
#include "lldb/ValueObject/ValueObject.h"
1314
#include "lldb/lldb-defines.h"
1415
#include "lldb/lldb-forward.h"
1516
#include "lldb/lldb-private-enumerations.h"
@@ -21,7 +22,6 @@ namespace lldb_private {
2122
class CompilerType;
2223
class DataExtractor;
2324
class Status;
24-
class ValueObject;
2525
} // namespace lldb_private
2626

2727
namespace lldb_private {
@@ -58,8 +58,8 @@ class ValueObjectConstResultImpl {
5858
m_live_address_type = address_type;
5959
}
6060

61-
virtual lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
62-
AddressType *address_type = nullptr);
61+
virtual ValueObject::AddrAndType
62+
GetAddressOf(bool scalar_is_load_address = true);
6363

6464
virtual size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
6565
uint32_t item_count = 1);

lldb/source/API/SBValue.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,10 +1336,8 @@ lldb::SBAddress SBValue::GetAddress() {
13361336
if (value_sp) {
13371337
TargetSP target_sp(value_sp->GetTargetSP());
13381338
if (target_sp) {
1339-
lldb::addr_t value = LLDB_INVALID_ADDRESS;
1340-
const bool scalar_is_load_address = true;
1341-
AddressType addr_type;
1342-
value = value_sp->GetAddressOf(scalar_is_load_address, &addr_type);
1339+
auto [value, addr_type] =
1340+
value_sp->GetAddressOf(/*scalar_is_load_address=*/true);
13431341
if (addr_type == eAddressTypeFile) {
13441342
ModuleSP module_sp(value_sp->GetModule());
13451343
if (module_sp)

lldb/source/Commands/CommandObjectWatchpoint.cpp

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,6 @@ corresponding to the byte size of the data type.");
822822

823823
// We passed the sanity check for the command. Proceed to set the
824824
// watchpoint now.
825-
lldb::addr_t addr = 0;
826825
size_t size = 0;
827826

828827
VariableSP var_sp;
@@ -861,19 +860,7 @@ corresponding to the byte size of the data type.");
861860

862861
CompilerType compiler_type;
863862

864-
if (valobj_sp) {
865-
AddressType addr_type;
866-
addr = valobj_sp->GetAddressOf(false, &addr_type);
867-
if (addr_type == eAddressTypeLoad) {
868-
// We're in business.
869-
// Find out the size of this variable.
870-
size =
871-
m_option_watchpoint.watch_size.GetCurrentValue() == 0
872-
? llvm::expectedToOptional(valobj_sp->GetByteSize()).value_or(0)
873-
: m_option_watchpoint.watch_size.GetCurrentValue();
874-
}
875-
compiler_type = valobj_sp->GetCompilerType();
876-
} else {
863+
if (!valobj_sp) {
877864
const char *error_cstr = error.AsCString(nullptr);
878865
if (error_cstr)
879866
result.AppendError(error_cstr);
@@ -883,6 +870,16 @@ corresponding to the byte size of the data type.");
883870
command.GetArgumentAtIndex(0));
884871
return;
885872
}
873+
auto [addr, addr_type] = valobj_sp->GetAddressOf(false);
874+
if (addr_type == eAddressTypeLoad) {
875+
// We're in business.
876+
// Find out the size of this variable.
877+
size =
878+
m_option_watchpoint.watch_size.GetCurrentValue() == 0
879+
? llvm::expectedToOptional(valobj_sp->GetByteSize()).value_or(0)
880+
: m_option_watchpoint.watch_size.GetCurrentValue();
881+
}
882+
compiler_type = valobj_sp->GetCompilerType();
886883

887884
// Now it's time to create the watchpoint.
888885
uint32_t watch_type = 0;

lldb/source/DataFormatters/CXXFunctionPointer.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ using namespace lldb_private::formatters;
2424
bool lldb_private::formatters::CXXFunctionPointerSummaryProvider(
2525
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
2626
StreamString sstr;
27-
AddressType func_ptr_address_type = eAddressTypeInvalid;
28-
addr_t func_ptr_address = valobj.GetPointerValue(&func_ptr_address_type);
27+
auto [func_ptr_address, func_ptr_address_type] = valobj.GetPointerValue();
2928
if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) {
3029
switch (func_ptr_address_type) {
3130
case eAddressTypeInvalid:

lldb/source/DataFormatters/FormattersHelpers.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,16 @@ lldb_private::formatters::ExtractIndexFromString(const char *item_name) {
113113

114114
Address
115115
lldb_private::formatters::GetArrayAddressOrPointerValue(ValueObject &valobj) {
116-
lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
117-
AddressType type;
116+
ValueObject::AddrAndType data_addr;
118117

119118
if (valobj.IsPointerType())
120-
data_addr = valobj.GetPointerValue(&type);
119+
data_addr = valobj.GetPointerValue();
121120
else if (valobj.IsArrayType())
122-
data_addr = valobj.GetAddressOf(/*scalar_is_load_address=*/true, &type);
123-
if (data_addr != LLDB_INVALID_ADDRESS && type == eAddressTypeFile)
124-
return Address(data_addr, valobj.GetModule()->GetSectionList());
121+
data_addr = valobj.GetAddressOf(/*scalar_is_load_address=*/true);
125122

126-
return data_addr;
123+
if (data_addr.address != LLDB_INVALID_ADDRESS &&
124+
data_addr.type == eAddressTypeFile)
125+
return Address(data_addr.address, valobj.GetModule()->GetSectionList());
126+
127+
return data_addr.address;
127128
}

lldb/source/DataFormatters/TypeFormat.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ bool TypeFormatImpl_Format::FormatObject(ValueObject *valobj,
8080
Status error;
8181
WritableDataBufferSP buffer_sp(
8282
new DataBufferHeap(max_len + 1, 0));
83-
Address address(valobj->GetPointerValue());
83+
Address address(valobj->GetPointerValue().address);
8484
target_sp->ReadCStringFromMemory(
8585
address, (char *)buffer_sp->GetBytes(), max_len, error);
8686
if (error.Success())

lldb/source/DataFormatters/ValueObjectPrinter.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,8 +542,7 @@ bool ValueObjectPrinter::ShouldPrintChildren(
542542
if (is_ptr || is_ref) {
543543
// We have a pointer or reference whose value is an address. Make sure
544544
// that address is not NULL
545-
AddressType ptr_address_type;
546-
if (valobj.GetPointerValue(&ptr_address_type) == 0)
545+
if (valobj.GetPointerValue().address == 0)
547546
return false;
548547

549548
const bool is_root_level = m_curr_depth == 0;

0 commit comments

Comments
 (0)