Index: include/lldb/Utility/DataExtractor.h =================================================================== --- include/lldb/Utility/DataExtractor.h +++ include/lldb/Utility/DataExtractor.h @@ -589,7 +589,7 @@ /// The sign extended signed integer value that was extracted, /// or zero on failure. //------------------------------------------------------------------ - int64_t GetMaxS64(lldb::offset_t *offset_ptr, size_t size) const; + int64_t GetMaxS64(lldb::offset_t *offset_ptr, size_t byte_size) const; //------------------------------------------------------------------ /// Extract an unsigned integer of size \a byte_size from \a Index: source/Core/DumpDataExtractor.cpp =================================================================== --- source/Core/DumpDataExtractor.cpp +++ source/Core/DumpDataExtractor.cpp @@ -272,6 +272,13 @@ case eFormatChar: case eFormatCharPrintable: case eFormatCharArray: { + // Reject invalid item_byte_size. + if (item_byte_size > 8) { + s->Printf("error: unsupported byte size (%" PRIu64 ") for char format", + (uint64_t)item_byte_size); + return offset; + } + // If we are only printing one character surround it with single // quotes if (item_count == 1 && item_format == eFormatChar) Index: source/Utility/DataExtractor.cpp =================================================================== --- source/Utility/DataExtractor.cpp +++ source/Utility/DataExtractor.cpp @@ -563,21 +563,8 @@ //---------------------------------------------------------------------- uint32_t DataExtractor::GetMaxU32(offset_t *offset_ptr, size_t byte_size) const { - switch (byte_size) { - case 1: - return GetU8(offset_ptr); - break; - case 2: - return GetU16(offset_ptr); - break; - case 4: - return GetU32(offset_ptr); - break; - default: - assert(false && "GetMaxU32 unhandled case!"); - break; - } - return 0; + assert(byte_size <= 4 && "GetMaxU32 unhandled case!"); + return GetMaxU64(offset_ptr, byte_size); } //---------------------------------------------------------------------- @@ -590,68 +577,63 @@ // // RETURNS the integer value that was extracted, or zero on failure. //---------------------------------------------------------------------- -uint64_t DataExtractor::GetMaxU64(offset_t *offset_ptr, size_t size) const { - switch (size) { +uint64_t DataExtractor::GetMaxU64(offset_t *offset_ptr, + size_t byte_size) const { + assert(byte_size <= 8 && "GetMax64 unhandled case!"); + switch (byte_size) { case 1: return GetU8(offset_ptr); - break; case 2: return GetU16(offset_ptr); - break; case 4: return GetU32(offset_ptr); - break; case 8: return GetU64(offset_ptr); - break; - default: - assert(false && "GetMax64 unhandled case!"); - break; + default: { + // General case. + const uint8_t *data = + static_cast(GetData(offset_ptr, byte_size)); + if (data == nullptr) + return 0; + + uint64_t res = 0; + if (m_byte_order == eByteOrderBig) + for (size_t i = 0; i < byte_size; ++i) + res = (res << 8) | data[i]; + else { + assert(m_byte_order == eByteOrderLittle); + for (size_t i = 0; i < byte_size; ++i) + res = (res << 8) | data[byte_size - 1 - i]; + } + return res; + } } return 0; } uint64_t DataExtractor::GetMaxU64_unchecked(offset_t *offset_ptr, - size_t size) const { - switch (size) { + size_t byte_size) const { + switch (byte_size) { case 1: return GetU8_unchecked(offset_ptr); - break; case 2: return GetU16_unchecked(offset_ptr); - break; case 4: return GetU32_unchecked(offset_ptr); - break; case 8: return GetU64_unchecked(offset_ptr); - break; default: - assert(false && "GetMax64 unhandled case!"); - break; + llvm_unreachable("GetMax64_unchecked unhandled case!"); } return 0; } -int64_t DataExtractor::GetMaxS64(offset_t *offset_ptr, size_t size) const { - switch (size) { - case 1: - return (int8_t)GetU8(offset_ptr); - break; - case 2: - return (int16_t)GetU16(offset_ptr); - break; - case 4: - return (int32_t)GetU32(offset_ptr); - break; - case 8: - return (int64_t)GetU64(offset_ptr); - break; - default: - assert(false && "GetMax64 unhandled case!"); - break; - } - return 0; +int64_t DataExtractor::GetMaxS64(offset_t *offset_ptr, size_t byte_size) const { + if (byte_size == 0) + return 0; + + uint64_t u64 = GetMaxU64(offset_ptr, byte_size); + return llvm::SignExtend64(u64, 8 * byte_size); } uint64_t DataExtractor::GetMaxU64Bitfield(offset_t *offset_ptr, size_t size, Index: unittests/Core/DataExtractorTest.cpp =================================================================== --- unittests/Core/DataExtractorTest.cpp +++ unittests/Core/DataExtractorTest.cpp @@ -49,3 +49,86 @@ EXPECT_EQ(buffer + 4, E.PeekData(4, 0)); EXPECT_EQ(nullptr, E.PeekData(4, 1)); } + +TEST(DataExtractorTest, GetMaxU64) { + uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; + DataExtractor LE(buffer, sizeof(buffer), lldb::eByteOrderLittle, + sizeof(void *)); + DataExtractor BE(buffer, sizeof(buffer), lldb::eByteOrderBig, sizeof(void *)); + + lldb::offset_t offset; + + // Check cases at the lower end with the byte size equal to 0 and 1. + offset = 0; + EXPECT_EQ(0U, LE.GetMaxU64(&offset, 0)); + EXPECT_EQ(0U, offset); + offset = 0; + EXPECT_EQ(0U, BE.GetMaxU64(&offset, 0)); + EXPECT_EQ(0U, offset); + + offset = 0; + EXPECT_EQ(0x01U, LE.GetMaxU64(&offset, 1)); + EXPECT_EQ(1U, offset); + offset = 0; + EXPECT_EQ(0x01U, BE.GetMaxU64(&offset, 1)); + EXPECT_EQ(1U, offset); + + // Check with a non-zero offset. + offset = 1; + EXPECT_EQ(0x0302U, LE.GetMaxU64(&offset, 2)); + EXPECT_EQ(3U, offset); + offset = 1; + EXPECT_EQ(0x0203U, BE.GetMaxU64(&offset, 2)); + EXPECT_EQ(3U, offset); + + // Check with the byte size not being a multiple of 2. + offset = 0; + EXPECT_EQ(0x07060504030201U, LE.GetMaxU64(&offset, 7)); + EXPECT_EQ(7U, offset); + offset = 0; + EXPECT_EQ(0x01020304050607U, BE.GetMaxU64(&offset, 7)); + EXPECT_EQ(7U, offset); + + // Check with the maximum allowed byte size. + offset = 0; + EXPECT_EQ(0x0807060504030201U, LE.GetMaxU64(&offset, 8)); + EXPECT_EQ(8U, offset); + offset = 0; + EXPECT_EQ(0x0102030405060708U, BE.GetMaxU64(&offset, 8)); + EXPECT_EQ(8U, offset); +} + +TEST(DataExtractorTest, GetMaxS64) { + uint8_t buffer[] = {0x01, 0x02, 0x83, 0x04, 0x05, 0x06, 0x07, 0x08}; + DataExtractor LE(buffer, sizeof(buffer), lldb::eByteOrderLittle, + sizeof(void *)); + DataExtractor BE(buffer, sizeof(buffer), lldb::eByteOrderBig, sizeof(void *)); + + lldb::offset_t offset; + + // Check a trivial case with the byte size equal to 0. + offset = 0; + EXPECT_EQ(0, LE.GetMaxS64(&offset, 0)); + EXPECT_EQ(0U, offset); + offset = 0; + EXPECT_EQ(0, BE.GetMaxS64(&offset, 0)); + EXPECT_EQ(0U, offset); + + // Check that sign extension works correctly. + offset = 0; + int64_t value = LE.GetMaxS64(&offset, 3); + EXPECT_EQ(0xffffffffff830201U, *reinterpret_cast(&value)); + EXPECT_EQ(3U, offset); + offset = 2; + value = BE.GetMaxS64(&offset, 3); + EXPECT_EQ(0xffffffffff830405U, *reinterpret_cast(&value)); + EXPECT_EQ(5U, offset); + + // Check with the maximum allowed byte size. + offset = 0; + EXPECT_EQ(0x0807060504830201, LE.GetMaxS64(&offset, 8)); + EXPECT_EQ(8U, offset); + offset = 0; + EXPECT_EQ(0x0102830405060708, BE.GetMaxS64(&offset, 8)); + EXPECT_EQ(8U, offset); +}