Don't allow SBValue::Cast to cast from a smaller type to a larger,

as we don't in general know where the extra data should come from.

Differential Revision: https://reviews.llvm.org/D153657
This commit is contained in:
Jim Ingham 2023-06-26 16:01:18 -07:00
parent 4cf35a85c7
commit f05e2fb013
13 changed files with 75 additions and 13 deletions

View File

@ -614,7 +614,9 @@ public:
virtual void SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS,
AddressType address_type = eAddressTypeLoad) {}
virtual lldb::ValueObjectSP Cast(const CompilerType &compiler_type);
lldb::ValueObjectSP Cast(const CompilerType &compiler_type);
virtual lldb::ValueObjectSP DoCast(const CompilerType &compiler_type);
virtual lldb::ValueObjectSP CastPointerType(const char *name,
CompilerType &ast_type);

View File

@ -106,7 +106,7 @@ public:
lldb::LanguageType GetPreferredDisplayLanguage() override;
lldb::ValueObjectSP Cast(const CompilerType &compiler_type) override;
lldb::ValueObjectSP DoCast(const CompilerType &compiler_type) override;
protected:
bool UpdateValue() override;

View File

@ -51,7 +51,7 @@ public:
size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
uint32_t item_count = 1) override;
lldb::ValueObjectSP Cast(const CompilerType &compiler_type) override;
lldb::ValueObjectSP DoCast(const CompilerType &compiler_type) override;
protected:
ValueObjectConstResultImpl m_impl;

View File

@ -60,7 +60,7 @@ public:
size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
uint32_t item_count = 1) override;
lldb::ValueObjectSP Cast(const CompilerType &compiler_type) override;
lldb::ValueObjectSP DoCast(const CompilerType &compiler_type) override;
protected:
ValueObjectConstResultImpl m_impl;

View File

@ -2604,6 +2604,17 @@ FileCheck output:
if not obj.Success():
error = obj.GetCString()
self.fail(self._formatMessage(msg, "'{}' is not success".format(error)))
"""Assert that an lldb.SBError is in the "failure" state."""
def assertFailure(self, obj, error_str = None, msg=None):
if obj.Success():
self.fail(self._formatMessage(msg, "Error not in a fail state"))
if error_str == None:
return
error = obj.GetCString()
self.assertEqual(error, error_str, msg)
"""Assert that a command return object is successful"""

View File

@ -2779,8 +2779,30 @@ ValueObjectSP ValueObject::AddressOf(Status &error) {
return m_addr_of_valobj_sp;
}
ValueObjectSP ValueObject::DoCast(const CompilerType &compiler_type) {
return ValueObjectCast::Create(*this, GetName(), compiler_type);
}
ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) {
return ValueObjectCast::Create(*this, GetName(), compiler_type);
// Only allow casts if the original type is equal or larger than the cast
// type. We don't know how to fetch more data for all the ConstResult types,
// so we can't guarantee this will work:
Status error;
CompilerType my_type = GetCompilerType();
ExecutionContextScope *exe_scope
= ExecutionContext(GetExecutionContextRef())
.GetBestExecutionContextScope();
if (compiler_type.GetByteSize(exe_scope)
<= GetCompilerType().GetByteSize(exe_scope)) {
return DoCast(compiler_type);
}
error.SetErrorString("Can only cast to a type that is equal to or smaller "
"than the orignal type.");
return ValueObjectConstResult::Create(
ExecutionContext(GetExecutionContextRef()).GetBestExecutionContextScope(),
error);
}
lldb::ValueObjectSP ValueObject::Clone(ConstString new_name) {

View File

@ -294,7 +294,7 @@ ValueObjectConstResult::GetDynamicValue(lldb::DynamicValueType use_dynamic) {
}
lldb::ValueObjectSP
ValueObjectConstResult::Cast(const CompilerType &compiler_type) {
ValueObjectConstResult::DoCast(const CompilerType &compiler_type) {
return m_impl.Cast(compiler_type);
}

View File

@ -57,6 +57,6 @@ size_t ValueObjectConstResultCast::GetPointeeData(DataExtractor &data,
}
lldb::ValueObjectSP
ValueObjectConstResultCast::Cast(const CompilerType &compiler_type) {
ValueObjectConstResultCast::DoCast(const CompilerType &compiler_type) {
return m_impl.Cast(compiler_type);
}

View File

@ -69,6 +69,6 @@ size_t ValueObjectConstResultChild::GetPointeeData(DataExtractor &data,
}
lldb::ValueObjectSP
ValueObjectConstResultChild::Cast(const CompilerType &compiler_type) {
ValueObjectConstResultChild::DoCast(const CompilerType &compiler_type) {
return m_impl.Cast(compiler_type);
}

View File

@ -607,11 +607,13 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
if (idx == 1) {
if (auto ptr_sp = valobj_sp->GetChildMemberWithName("__ptr_")) {
Status status;
auto value_sp = ptr_sp->Dereference(status);
auto value_type_sp =
valobj_sp->GetCompilerType()
.GetTypeTemplateArgument(0).GetPointerType();
ValueObjectSP cast_ptr_sp = ptr_sp->Cast(value_type_sp);
ValueObjectSP value_sp = cast_ptr_sp->Dereference(status);
if (status.Success()) {
auto value_type_sp =
valobj_sp->GetCompilerType().GetTypeTemplateArgument(0);
return value_sp->Cast(value_type_sp);
return value_sp;
}
}
}

View File

@ -157,7 +157,11 @@ lldb::ValueObjectSP lldb_private::formatters::
}
if (!m_node_type)
return nullptr;
node_sp = node_sp->Cast(m_node_type);
node_sp = m_next_element->Cast(m_node_type.GetPointerType())
->Dereference(error);
if (!node_sp || error.Fail())
return nullptr;
value_sp = node_sp->GetChildMemberWithName("__value_");
hash_sp = node_sp->GetChildMemberWithName("__hash_");
if (!value_sp || !hash_sp)

View File

@ -146,6 +146,19 @@ class ValueAPITestCase(TestBase):
self.assertTrue(val_s.GetChildMemberWithName("a").AddressOf(), VALID_VARIABLE)
self.assertTrue(val_a.Cast(val_i.GetType()).AddressOf(), VALID_VARIABLE)
# Test some other cases of the Cast API. We allow casts from one struct type
# to another, which is a little weird, but we don't support casting from a
# smaller type to a larger as we often wouldn't know how to get the extra data:
val_f = target.EvaluateExpression("f")
bad_cast = val_s.Cast(val_f.GetType())
self.assertFailure(bad_cast.GetError(),
"Can only cast to a type that is equal to or smaller than the orignal type.")
weird_cast = val_f.Cast(val_s.GetType())
self.assertSuccess(weird_cast.GetError(),
"Can cast from a larger to a smaller")
self.assertEqual(weird_cast.GetChildMemberWithName("a").GetValueAsSigned(0), 33,
"Got the right value")
# Check that lldb.value implements truth testing.
self.assertFalse(lldb.value(frame0.FindVariable("bogus")))
self.assertTrue(lldb.value(frame0.FindVariable("uinthex")))

View File

@ -29,6 +29,13 @@ struct MyStruct
int b;
};
struct MyBiggerStruct
{
int a;
int b;
int c;
};
int main (int argc, char const *argv[])
{
uint32_t uinthex = 0xE0A35F10;
@ -37,6 +44,7 @@ int main (int argc, char const *argv[])
int i;
MyInt a = 12345;
struct MyStruct s = { 11, 22 };
struct MyBiggerStruct f = { 33, 44, 55 };
int *my_int_ptr = &g_my_int;
printf("my_int_ptr points to location %p\n", my_int_ptr);
const char **str_ptr = days_of_week;