Fixed 2 more issues found by the address sanitizer:

1 - A store off the end of a buffer in ValueObject.cpp
2 - DataExtractor had cases where bad offsets could cause invalid memory to be accessed.

llvm-svn: 174757
This commit is contained in:
Greg Clayton 2013-02-08 22:02:02 +00:00
parent b2f426c40e
commit 2452ab7fa8
6 changed files with 242 additions and 228 deletions

View File

@ -434,7 +434,13 @@ public:
/// and length are valid, or NULL otherwise.
//------------------------------------------------------------------
const void*
GetData (lldb::offset_t *offset_ptr, lldb::offset_t length) const;
GetData (lldb::offset_t *offset_ptr, lldb::offset_t length) const
{
const uint8_t *ptr = PeekData (*offset_ptr, length);
if (ptr)
*offset_ptr += length;
return ptr;
}
//------------------------------------------------------------------
/// Copy \a dst_len bytes from \a *offset_ptr and ensure the copied
@ -1066,7 +1072,12 @@ public:
/// otherwise.
//------------------------------------------------------------------
const uint8_t*
PeekData (lldb::offset_t offset, lldb::offset_t length) const;
PeekData (lldb::offset_t offset, lldb::offset_t length) const
{
if (length > 0 && ValidOffsetForDataOfSize(offset, length))
return m_start + offset;
return NULL;
}
//------------------------------------------------------------------
/// Set the address byte size.
@ -1221,7 +1232,11 @@ public:
/// length bytes available at that offset, \b false otherwise.
//------------------------------------------------------------------
bool
ValidOffsetForDataOfSize (lldb::offset_t offset, lldb::offset_t length) const;
ValidOffsetForDataOfSize (lldb::offset_t offset, lldb::offset_t length) const
{
lldb::offset_t bytes_left = BytesLeft (offset);
return length <= bytes_left;
}
size_t
Copy (DataExtractor& dest_data) const;
@ -1233,6 +1248,16 @@ public:
Append (void* bytes, lldb::offset_t length);
protected:
lldb::offset_t
BytesLeft (lldb::offset_t offset) const
{
const lldb::offset_t size = GetByteSize();
if (offset >= size)
return 0;
return offset - size;
}
//------------------------------------------------------------------
// Member variables
//------------------------------------------------------------------

View File

@ -620,6 +620,9 @@ public:
virtual lldb::LanguageType
GetObjectRuntimeLanguage();
virtual uint32_t
GetTypeInfo (lldb::clang_type_t *pointee_or_element_clang_type = NULL);
virtual bool
IsPointerType ();

View File

@ -107,6 +107,9 @@ public:
GetTypeNameForOpaqueQualType (clang::ASTContext *ast,
lldb::clang_type_t opaque_qual_type);
uint32_t
GetClangTypeByteSize ();
uint32_t
GetClangTypeBitWidth ();

View File

@ -54,6 +54,23 @@ ReadInt64(const unsigned char* ptr, offset_t offset)
return *(uint64_t *)(ptr + offset);
}
static inline uint16_t
ReadInt16(const void* ptr)
{
return *(uint16_t *)(ptr);
}
static inline uint32_t
ReadInt32 (const void* ptr)
{
return *(uint32_t *)(ptr);
}
static inline uint64_t
ReadInt64(const void* ptr)
{
return *(uint64_t *)(ptr);
}
static inline uint16_t
ReadSwapInt16(const unsigned char* ptr, offset_t offset)
{
@ -71,6 +88,23 @@ ReadSwapInt64(const unsigned char* ptr, offset_t offset)
return llvm::ByteSwap_64(*(uint64_t *)(ptr + offset));
}
static inline uint16_t
ReadSwapInt16(const void* ptr)
{
return llvm::ByteSwap_16(*(uint16_t *)(ptr));
}
static inline uint32_t
ReadSwapInt32 (const void* ptr)
{
return llvm::ByteSwap_32(*(uint32_t *)(ptr));
}
static inline uint64_t
ReadSwapInt64(const void* ptr)
{
return llvm::ByteSwap_64(*(uint64_t *)(ptr));
}
#define NON_PRINTABLE_CHAR '.'
//----------------------------------------------------------------------
// Default constructor.
@ -208,32 +242,6 @@ DataExtractor::GetSharedDataOffset () const
return 0;
}
//------------------------------------------------------------------
// Returns true if there are LENGTH bytes availabe starting OFFSET
// into the data that is in this object.
//------------------------------------------------------------------
bool
DataExtractor::ValidOffsetForDataOfSize (offset_t offset, offset_t length) const
{
offset_t size = GetByteSize();
if (offset >= size)
return false; // offset isn't valid
if (length == 0)
return true; // No bytes requested at this offset, return true
// If we flip the bits in offset we can figure out how
// many bytes we have left before "offset + length"
// could overflow when doing unsigned arithmetic.
if (length > ~offset)
return false; // unsigned overflow
// Make sure "offset + length" is a valid offset as well.
// length must be greater than zero for this to be a
// valid expression, and we have already checked for this.
return ((offset + length) <= size);
}
//----------------------------------------------------------------------
// Set the data with which this object will extract from to data
// starting at BYTES and set the length of the data to LENGTH bytes
@ -354,13 +362,10 @@ DataExtractor::SetData (const DataBufferSP& data_sp, offset_t data_offset, offse
uint8_t
DataExtractor::GetU8 (offset_t *offset_ptr) const
{
uint8_t val = 0;
if ( m_start < m_end )
{
val = m_start[*offset_ptr];
*offset_ptr += sizeof(val);
}
return val;
const uint8_t *data = (const uint8_t *)GetData (offset_ptr, 1);
if (data)
return *data;
return 0;
}
//----------------------------------------------------------------------
@ -375,14 +380,11 @@ DataExtractor::GetU8 (offset_t *offset_ptr) const
void *
DataExtractor::GetU8 (offset_t *offset_ptr, void *dst, uint32_t count) const
{
lldb::offset_t offset = *offset_ptr;
if ((count > 0) && ValidOffsetForDataOfSize(offset, count) )
const uint8_t *data = (const uint8_t *)GetData (offset_ptr, count);
if (data)
{
// Copy the data into the buffer
memcpy (dst, m_start + offset, count);
// Advance the offset
*offset_ptr += count;
memcpy (dst, data, count);
// Return a non-NULL pointer to the converted data as an indicator of success
return dst;
}
@ -399,16 +401,13 @@ uint16_t
DataExtractor::GetU16 (offset_t *offset_ptr) const
{
uint16_t val = 0;
lldb::offset_t offset = *offset_ptr;
if ( ValidOffsetForDataOfSize(offset, sizeof(val)) )
const uint8_t *data = (const uint8_t *)GetData (offset_ptr, sizeof(val));
if (data)
{
if (m_byte_order != lldb::endian::InlHostByteOrder())
val = ReadSwapInt16(m_start, offset);
val = ReadSwapInt16(data);
else
val = ReadInt16 (m_start, offset);
// Advance the offset
*offset_ptr += sizeof(val);
val = ReadInt16 (data);
}
return val;
}
@ -416,9 +415,11 @@ DataExtractor::GetU16 (offset_t *offset_ptr) const
uint16_t
DataExtractor::GetU16_unchecked (offset_t *offset_ptr) const
{
uint16_t val = (m_byte_order == lldb::endian::InlHostByteOrder()) ?
ReadInt16 (m_start, *offset_ptr) :
ReadSwapInt16(m_start, *offset_ptr);
uint16_t val;
if (m_byte_order == lldb::endian::InlHostByteOrder())
val = ReadInt16 (m_start, *offset_ptr);
else
val = ReadSwapInt16(m_start, *offset_ptr);
*offset_ptr += sizeof(val);
return val;
}
@ -426,9 +427,11 @@ DataExtractor::GetU16_unchecked (offset_t *offset_ptr) const
uint32_t
DataExtractor::GetU32_unchecked (offset_t *offset_ptr) const
{
uint32_t val = (m_byte_order == lldb::endian::InlHostByteOrder()) ?
ReadInt32 (m_start, *offset_ptr) :
ReadSwapInt32 (m_start, *offset_ptr);
uint32_t val;
if (m_byte_order == lldb::endian::InlHostByteOrder())
val = ReadInt32 (m_start, *offset_ptr);
else
val = ReadSwapInt32 (m_start, *offset_ptr);
*offset_ptr += sizeof(val);
return val;
}
@ -436,9 +439,11 @@ DataExtractor::GetU32_unchecked (offset_t *offset_ptr) const
uint64_t
DataExtractor::GetU64_unchecked (offset_t *offset_ptr) const
{
uint64_t val = (m_byte_order == lldb::endian::InlHostByteOrder()) ?
ReadInt64 (m_start, *offset_ptr) :
ReadSwapInt64 (m_start, *offset_ptr);
uint64_t val;
if (m_byte_order == lldb::endian::InlHostByteOrder())
val = ReadInt64 (m_start, *offset_ptr);
else
val = ReadSwapInt64 (m_start, *offset_ptr);
*offset_ptr += sizeof(val);
return val;
}
@ -456,29 +461,28 @@ DataExtractor::GetU64_unchecked (offset_t *offset_ptr) const
void *
DataExtractor::GetU16 (offset_t *offset_ptr, void *void_dst, uint32_t count) const
{
uint16_t *dst = (uint16_t *)void_dst;
const size_t value_size = sizeof(*dst);
lldb::offset_t offset = *offset_ptr;
if ((count > 0) && ValidOffsetForDataOfSize(offset, value_size * count) )
const size_t src_size = sizeof(uint16_t) * count;
const uint16_t *src = (const uint16_t *)GetData (offset_ptr, src_size);
if (src)
{
uint16_t *value_ptr;
uint16_t *end = dst + count;
if (m_byte_order != lldb::endian::InlHostByteOrder())
{
for (value_ptr = dst; value_ptr < end; ++value_ptr, offset += value_size)
*value_ptr = ReadSwapInt16 (m_start, offset);
uint16_t *dst_pos = (uint16_t *)void_dst;
uint16_t *dst_end = dst_pos + count;
const uint16_t *src_pos = src;
while (dst_pos < dst_end)
{
*dst_pos = ReadSwapInt16 (src_pos);
++dst_pos;
++src_pos;
}
}
else
{
for (value_ptr = dst; value_ptr < end; ++value_ptr, offset += value_size)
*value_ptr = ReadInt16 (m_start, offset);
memcpy (void_dst, src, src_size);
}
// Advance the offset
*offset_ptr = offset;
// Return a non-NULL pointer to the converted data as an indicator of success
return dst;
return void_dst;
}
return NULL;
}
@ -493,17 +497,13 @@ uint32_t
DataExtractor::GetU32 (offset_t *offset_ptr) const
{
uint32_t val = 0;
lldb::offset_t offset = *offset_ptr;
if ( ValidOffsetForDataOfSize(offset, sizeof(val)) )
const uint32_t *data = (const uint32_t *)GetData (offset_ptr, sizeof(val));
if (data)
{
if (m_byte_order != lldb::endian::InlHostByteOrder())
val = ReadSwapInt32 (m_start, offset);
val = ReadSwapInt32 (data);
else
val = ReadInt32 (m_start, offset);
// Advance the offset
*offset_ptr += sizeof(val);
val = *data;
}
return val;
}
@ -520,30 +520,28 @@ DataExtractor::GetU32 (offset_t *offset_ptr) const
void *
DataExtractor::GetU32 (offset_t *offset_ptr, void *void_dst, uint32_t count) const
{
uint32_t *dst = (uint32_t *)void_dst;
const size_t value_size = sizeof(*dst);
lldb::offset_t offset = *offset_ptr;
if ((count > 0) && ValidOffsetForDataOfSize(offset, value_size * count))
const size_t src_size = sizeof(uint32_t) * count;
const uint32_t *src = (const uint32_t *)GetData (offset_ptr, src_size);
if (src)
{
uint32_t *value_ptr;
uint32_t *end = dst + count;
if (m_byte_order != lldb::endian::InlHostByteOrder())
{
for (value_ptr = dst; value_ptr < end; ++value_ptr, offset += value_size)
*value_ptr = ReadSwapInt32 (m_start, offset);
uint32_t *dst_pos = (uint32_t *)void_dst;
uint32_t *dst_end = dst_pos + count;
const uint32_t *src_pos = src;
while (dst_pos < dst_end)
{
*dst_pos = ReadSwapInt32 (src_pos);
++dst_pos;
++src_pos;
}
}
else
{
for (value_ptr = dst; value_ptr < end; ++value_ptr, offset += value_size)
*value_ptr = ReadInt32 (m_start, offset);
memcpy (void_dst, src, src_size);
}
// Advance the offset
*offset_ptr = offset;
// Return a non-NULL pointer to the converted data as an indicator of success
return dst;
return void_dst;
}
return NULL;
}
@ -558,16 +556,13 @@ uint64_t
DataExtractor::GetU64 (offset_t *offset_ptr) const
{
uint64_t val = 0;
lldb::offset_t offset = *offset_ptr;
if ( ValidOffsetForDataOfSize(offset, sizeof(val)) )
const uint64_t *data = (const uint64_t *)GetData (offset_ptr, sizeof(val));
if (data)
{
if (m_byte_order != lldb::endian::InlHostByteOrder())
val = ReadSwapInt64 (m_start, offset);
val = ReadSwapInt64 (data);
else
val = ReadInt64 (m_start, offset);
// Advance the offset
*offset_ptr += sizeof(val);
val = *data;
}
return val;
}
@ -582,30 +577,28 @@ DataExtractor::GetU64 (offset_t *offset_ptr) const
void *
DataExtractor::GetU64 (offset_t *offset_ptr, void *void_dst, uint32_t count) const
{
uint64_t *dst = (uint64_t *)void_dst;
const size_t value_size = sizeof(uint64_t);
lldb::offset_t offset = *offset_ptr;
if ((count > 0) && ValidOffsetForDataOfSize(offset, value_size * count))
const size_t src_size = sizeof(uint64_t) * count;
const uint64_t *src = (const uint64_t *)GetData (offset_ptr, src_size);
if (src)
{
uint64_t *value_ptr;
uint64_t *end = dst + count;
if (m_byte_order != lldb::endian::InlHostByteOrder())
{
for (value_ptr = dst; value_ptr < end; ++value_ptr, offset += value_size)
*value_ptr = ReadSwapInt64 (m_start, offset);
uint64_t *dst_pos = (uint64_t *)void_dst;
uint64_t *dst_end = dst_pos + count;
const uint64_t *src_pos = src;
while (dst_pos < dst_end)
{
*dst_pos = ReadSwapInt64 (src_pos);
++dst_pos;
++src_pos;
}
}
else
{
for (value_ptr = dst; value_ptr < end; ++value_ptr, offset += value_size)
*value_ptr = ReadInt64 (m_start, offset);
memcpy (void_dst, src, src_size);
}
// Advance the offset
*offset_ptr = offset;
// Return a non-NULL pointer to the converted data as an indicator of success
return dst;
return void_dst;
}
return NULL;
}
@ -732,19 +725,20 @@ DataExtractor::GetFloat (offset_t *offset_ptr) const
{
typedef float float_type;
float_type val = 0.0;
const uint8_t *src_data = PeekData (*offset_ptr, sizeof(float_type));
if (src_data)
const size_t src_size = sizeof(float_type);
const float_type *src = (const float_type *)GetData (offset_ptr, src_size);
if (src)
{
if (m_byte_order != lldb::endian::InlHostByteOrder())
{
const uint8_t *src_data = (const uint8_t *)src;
uint8_t *dst_data = (uint8_t *)&val;
for (int i=0; i<sizeof(float_type); ++i)
dst_data[sizeof(float_type) - 1 - i] = src_data[i];
}
else
{
::memcpy (&val, src_data, sizeof (float_type));
val = *src;
}
// Advance the offset
@ -758,21 +752,22 @@ DataExtractor::GetDouble (offset_t *offset_ptr) const
{
typedef double float_type;
float_type val = 0.0;
const uint8_t *src_data = PeekData (*offset_ptr, sizeof(float_type));
if (src_data)
const size_t src_size = sizeof(float_type);
const float_type *src = (const float_type *)GetData (offset_ptr, src_size);
if (src)
{
if (m_byte_order != lldb::endian::InlHostByteOrder())
{
const uint8_t *src_data = (const uint8_t *)src;
uint8_t *dst_data = (uint8_t *)&val;
for (int i=0; i<sizeof(float_type); ++i)
dst_data[sizeof(float_type) - 1 - i] = src_data[i];
}
else
{
::memcpy (&val, src_data, sizeof (float_type));
val = *src;
}
// Advance the offset
*offset_ptr += sizeof(val);
}
@ -785,21 +780,22 @@ DataExtractor::GetLongDouble (offset_t *offset_ptr) const
{
typedef long double float_type;
float_type val = 0.0;
const uint8_t *src_data = PeekData (*offset_ptr, sizeof(float_type));
if (src_data)
const size_t src_size = sizeof(float_type);
const float_type *src = (const float_type *)GetData (offset_ptr, src_size);
if (src)
{
if (m_byte_order != lldb::endian::InlHostByteOrder())
{
const uint8_t *src_data = (const uint8_t *)src;
uint8_t *dst_data = (uint8_t *)&val;
for (int i=0; i<sizeof(float_type); ++i)
dst_data[sizeof(float_type) - 1 - i] = src_data[i];
}
else
{
::memcpy (&val, src_data, sizeof (float_type));
val = *src;
}
// Advance the offset
*offset_ptr += sizeof(val);
}
@ -964,41 +960,6 @@ DataExtractor::ExtractBytes (offset_t offset, offset_t length, ByteOrder dst_byt
}
return 0;
}
//----------------------------------------------------------------------
// Peeks at bytes in the contained data.
//
// Returns a valid pointer to bytes if "offset" is a valid offset in
// and there are "length" bytes available, else NULL is returned.
//----------------------------------------------------------------------
const uint8_t*
DataExtractor::PeekData (offset_t offset, offset_t length) const
{
if ( length > 0 && ValidOffsetForDataOfSize(offset, length) )
return m_start + offset;
return NULL;
}
//----------------------------------------------------------------------
// Returns a pointer to a bytes in this object's data at the offset
// pointed to by "offset_ptr". If "length" is zero or too large,
// then the offset pointed to by "offset_ptr" will not be updated
// and NULL will be returned.
//
// Returns a pointer to the data if the offset and length are valid,
// or NULL otherwise.
//----------------------------------------------------------------------
const void*
DataExtractor::GetData (offset_t *offset_ptr, offset_t length) const
{
const uint8_t* bytes = NULL;
lldb::offset_t offset = *offset_ptr;
if ( length > 0 && ValidOffsetForDataOfSize(offset, length) )
{
bytes = m_start + offset;
*offset_ptr = offset + length;
}
return bytes;
}
// Extract data and swap if needed when doing the copy
lldb::offset_t
@ -1129,20 +1090,29 @@ DataExtractor::CopyByteOrderedData (offset_t src_offset,
const char*
DataExtractor::GetCStr (offset_t *offset_ptr) const
{
const char *s = NULL;
if ( m_start < m_end )
const char *cstr = (const char *)PeekData (*offset_ptr, 1);
if (cstr)
{
s = (char*)m_start + *offset_ptr;
const char *cstr_end = cstr;
const char *end = (const char *)m_end;
while (cstr_end < end && *cstr_end)
++cstr_end;
size_t length = strlen(s) + 1;
if (!ValidOffsetForDataOfSize(*offset_ptr, length))
return NULL;
// Advance the offset
*offset_ptr += length;
// Now we are either at the end of the data or we point to the
// NULL C string terminator with cstr_end...
if (*cstr_end == '\0')
{
// Advance the offset with one extra byte for the NULL terminator
*offset_ptr += (cstr_end - cstr + 1);
return cstr;
}
// We reached the end of the data without finding a NULL C string
// terminator. Fall through and return NULL otherwise anyone that
// would have used the result as a C string can wonder into
// unknown memory...
}
return s;
return NULL;
}
//------------------------------------------------------------------
@ -1156,9 +1126,7 @@ DataExtractor::GetCStr (offset_t *offset_ptr) const
const char *
DataExtractor::PeekCStr (offset_t offset) const
{
if (ValidOffset (offset))
return (const char*)m_start + offset;
return NULL;
return (const char *)PeekData (offset, 1);
}
//----------------------------------------------------------------------
@ -1172,7 +1140,7 @@ DataExtractor::PeekCStr (offset_t offset) const
uint64_t
DataExtractor::GetULEB128 (offset_t *offset_ptr) const
{
const uint8_t *src = m_start + *offset_ptr;
const uint8_t *src = (const uint8_t *)PeekData (*offset_ptr, 1);
const uint8_t *end = m_end;
if (src < end)
@ -1191,7 +1159,7 @@ DataExtractor::GetULEB128 (offset_t *offset_ptr) const
shift += 7;
}
}
*offset_ptr = (uint32_t)(src - m_start);
*offset_ptr = src - m_start;
return result;
}
@ -1209,18 +1177,19 @@ DataExtractor::GetULEB128 (offset_t *offset_ptr) const
int64_t
DataExtractor::GetSLEB128 (offset_t *offset_ptr) const
{
int64_t result = 0;
if ( m_start < m_end )
const uint8_t *src = (const uint8_t *)PeekData (*offset_ptr, 1);
const uint8_t *end = m_end;
if (src < end)
{
int64_t result = 0;
int shift = 0;
int size = sizeof (uint32_t) * 8;
const uint8_t *src = m_start + *offset_ptr;
int size = sizeof (int64_t) * 8;
uint8_t byte = 0;
int bytecount = 0;
while (src < m_end)
while (src < end)
{
bytecount++;
byte = *src++;
@ -1235,8 +1204,9 @@ DataExtractor::GetSLEB128 (offset_t *offset_ptr) const
result |= - (1 << shift);
*offset_ptr += bytecount;
return result;
}
return result;
return 0;
}
//----------------------------------------------------------------------
@ -1251,15 +1221,15 @@ uint32_t
DataExtractor::Skip_LEB128 (offset_t *offset_ptr) const
{
uint32_t bytes_consumed = 0;
if ( m_start < m_end )
const uint8_t *src = (const uint8_t *)PeekData (*offset_ptr, 1);
const uint8_t *end = m_end;
if (src < end)
{
const uint8_t *start = m_start + *offset_ptr;
const uint8_t *src = start;
while ((src < m_end) && (*src++ & 0x80))
const uint8_t *src_pos = src;
while ((src_pos < end) && (*src_pos++ & 0x80))
++bytes_consumed;
*offset_ptr += src - start;
*offset_ptr += src_pos - src;
}
return bytes_consumed;
}

View File

@ -674,12 +674,9 @@ bool
ValueObject::MightHaveChildren()
{
bool has_children = false;
clang_type_t clang_type = GetClangType();
if (clang_type)
const uint32_t type_info = GetTypeInfo();
if (type_info)
{
const uint32_t type_info = ClangASTContext::GetTypeInfo (clang_type,
GetClangAST(),
NULL);
if (type_info & (ClangASTContext::eTypeHasChildren |
ClangASTContext::eTypeIsPointer |
ClangASTContext::eTypeIsReference))
@ -877,11 +874,9 @@ bool
ValueObject::IsCStringContainer(bool check_pointer)
{
clang_type_t elem_or_pointee_clang_type;
const Flags type_flags (ClangASTContext::GetTypeInfo (GetClangType(),
GetClangAST(),
&elem_or_pointee_clang_type));
const Flags type_flags (GetTypeInfo (&elem_or_pointee_clang_type));
bool is_char_arr_ptr (type_flags.AnySet (ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) &&
ClangASTContext::IsCharType (elem_or_pointee_clang_type));
ClangASTContext::IsCharType (elem_or_pointee_clang_type));
if (!is_char_arr_ptr)
return false;
if (!check_pointer)
@ -899,19 +894,20 @@ ValueObject::GetPointeeData (DataExtractor& data,
uint32_t item_idx,
uint32_t item_count)
{
if (!IsPointerType() && !IsArrayType())
clang_type_t pointee_or_element_clang_type;
const uint32_t type_info = GetTypeInfo (&pointee_or_element_clang_type);
const bool is_pointer_type = type_info & ClangASTContext::eTypeIsPointer;
const bool is_array_type = type_info & ClangASTContext::eTypeIsArray;
if (!(is_pointer_type || is_array_type))
return 0;
if (item_count == 0)
return 0;
uint32_t stride = 0;
clang::ASTContext *ast = GetClangAST();
ClangASTType pointee_or_element_type(ast, pointee_or_element_clang_type);
ClangASTType type(GetClangAST(),
GetClangType());
const uint64_t item_type_size = (IsPointerType() ? ClangASTType::GetTypeByteSize(GetClangAST(), type.GetPointeeType()) :
ClangASTType::GetTypeByteSize(GetClangAST(), type.GetArrayElementType(stride)));
const uint64_t item_type_size = pointee_or_element_type.GetClangTypeByteSize();
const uint64_t bytes = item_count * item_type_size;
@ -919,7 +915,7 @@ ValueObject::GetPointeeData (DataExtractor& data,
if (item_idx == 0 && item_count == 1) // simply a deref
{
if (IsPointerType())
if (is_pointer_type)
{
Error error;
ValueObjectSP pointee_sp = Dereference(error);
@ -943,7 +939,7 @@ ValueObject::GetPointeeData (DataExtractor& data,
lldb::DataBufferSP data_sp(heap_buf_ptr = new lldb_private::DataBufferHeap());
AddressType addr_type;
lldb::addr_t addr = IsPointerType() ? GetPointerValue(&addr_type) : GetAddressOf(true, &addr_type);
lldb::addr_t addr = is_pointer_type ? GetPointerValue(&addr_type) : GetAddressOf(true, &addr_type);
switch (addr_type)
{
@ -988,9 +984,15 @@ ValueObject::GetPointeeData (DataExtractor& data,
break;
case eAddressTypeHost:
{
heap_buf_ptr->CopyData((uint8_t*)(addr + offset), bytes);
data.SetData(data_sp);
return bytes;
ClangASTType valobj_type(ast, GetClangType());
uint64_t max_bytes = valobj_type.GetClangTypeByteSize();
if (max_bytes > offset)
{
size_t bytes_read = std::min<uint64_t>(max_bytes - offset, bytes);
heap_buf_ptr->CopyData((uint8_t*)(addr + offset), bytes_read);
data.SetData(data_sp);
return bytes_read;
}
}
break;
case eAddressTypeInvalid:
@ -1031,7 +1033,7 @@ strlen_or_inf (const char* str,
while(*str)
{
len++;str++;
if (len > maxlen)
if (len >= maxlen)
return maxlen_value;
}
}
@ -1053,9 +1055,7 @@ ValueObject::ReadPointedString (Stream& s,
clang_type_t clang_type = GetClangType();
clang_type_t elem_or_pointee_clang_type;
const Flags type_flags (ClangASTContext::GetTypeInfo (clang_type,
GetClangAST(),
&elem_or_pointee_clang_type));
const Flags type_flags (GetTypeInfo (&elem_or_pointee_clang_type));
if (type_flags.AnySet (ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) &&
ClangASTContext::IsCharType (elem_or_pointee_clang_type))
{
@ -1383,7 +1383,7 @@ ValueObject::HasSpecialPrintableRepresentation(ValueObjectRepresentationStyle va
Format custom_format)
{
clang_type_t elem_or_pointee_type;
Flags flags(ClangASTContext::GetTypeInfo(GetClangType(), GetClangAST(), &elem_or_pointee_type));
Flags flags(GetTypeInfo(&elem_or_pointee_type));
if (flags.AnySet(ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer)
&& val_obj_display == ValueObject::eValueObjectRepresentationStyleValue)
@ -1427,7 +1427,7 @@ ValueObject::DumpPrintableRepresentation(Stream& s,
{
clang_type_t elem_or_pointee_type;
Flags flags(ClangASTContext::GetTypeInfo(GetClangType(), GetClangAST(), &elem_or_pointee_type));
Flags flags(GetTypeInfo(&elem_or_pointee_type));
bool allow_special = ((special & ePrintableRepresentationSpecialCasesAllow) == ePrintableRepresentationSpecialCasesAllow);
bool only_special = ((special & ePrintableRepresentationSpecialCasesOnly) == ePrintableRepresentationSpecialCasesOnly);
@ -1843,6 +1843,12 @@ ValueObject::GetSyntheticChild (const ConstString &key) const
return synthetic_child_sp;
}
uint32_t
ValueObject::GetTypeInfo (clang_type_t *pointee_or_element_clang_type)
{
return ClangASTContext::GetTypeInfo (GetClangType(), GetClangAST(), pointee_or_element_clang_type);
}
bool
ValueObject::IsPointerType ()
{
@ -1896,10 +1902,11 @@ ValueObject::IsObjCNil ()
ValueObjectSP
ValueObject::GetSyntheticArrayMember (size_t index, bool can_create)
{
if (IsArrayType())
const uint32_t type_info = GetTypeInfo ();
if (type_info & ClangASTContext::eTypeIsArray)
return GetSyntheticArrayMemberFromArray(index, can_create);
if (IsPointerType())
if (type_info & ClangASTContext::eTypeIsPointer)
return GetSyntheticArrayMemberFromPointer(index, can_create);
return ValueObjectSP();

View File

@ -1200,6 +1200,12 @@ ClangASTType::DumpSummary
}
}
uint32_t
ClangASTType::GetClangTypeByteSize ()
{
return (GetClangTypeBitWidth (m_ast, m_type) + 7) / 8;
}
uint32_t
ClangASTType::GetClangTypeBitWidth ()
{