mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-19 03:25:54 -04:00
[DWARF] Better detect errors in Address Range Tables.
The patch tries to cover most remaining cases of wrong data. Differential Revision: https://reviews.llvm.org/D71932
This commit is contained in:
parent
6332990721
commit
ed9851a0a6
@ -59,9 +59,31 @@ Error DWARFDebugArangeSet::extract(DataExtractor data, uint64_t *offset_ptr) {
|
||||
// the segment selectors are omitted from all tuples, including
|
||||
// the terminating tuple.
|
||||
|
||||
constexpr unsigned CommonFieldsLength = 2 + // Version
|
||||
1 + // Address Size
|
||||
1; // Segment Selector Size
|
||||
constexpr unsigned DWARF32HeaderLength =
|
||||
dwarf::getUnitLengthFieldByteSize(dwarf::DWARF32) + CommonFieldsLength +
|
||||
dwarf::getDwarfOffsetByteSize(dwarf::DWARF32); // Debug Info Offset
|
||||
constexpr unsigned DWARF64HeaderLength =
|
||||
dwarf::getUnitLengthFieldByteSize(dwarf::DWARF64) + CommonFieldsLength +
|
||||
dwarf::getDwarfOffsetByteSize(dwarf::DWARF64); // Debug Info Offset
|
||||
|
||||
if (!data.isValidOffsetForDataOfSize(Offset, DWARF32HeaderLength))
|
||||
return createStringError(errc::invalid_argument,
|
||||
"section is not large enough to contain "
|
||||
"an address range table at offset 0x%" PRIx64,
|
||||
Offset);
|
||||
|
||||
dwarf::DwarfFormat format = dwarf::DWARF32;
|
||||
HeaderData.Length = data.getU32(offset_ptr);
|
||||
if (HeaderData.Length == dwarf::DW_LENGTH_DWARF64) {
|
||||
if (!data.isValidOffsetForDataOfSize(Offset, DWARF64HeaderLength))
|
||||
return createStringError(
|
||||
errc::invalid_argument,
|
||||
"section is not large enough to contain a DWARF64 "
|
||||
"address range table at offset 0x%" PRIx64,
|
||||
Offset);
|
||||
HeaderData.Length = data.getU64(offset_ptr);
|
||||
format = dwarf::DWARF64;
|
||||
} else if (HeaderData.Length >= dwarf::DW_LENGTH_lo_reserved) {
|
||||
@ -91,17 +113,38 @@ Error DWARFDebugArangeSet::extract(DataExtractor data, uint64_t *offset_ptr) {
|
||||
" has unsupported address size: %d "
|
||||
"(4 and 8 supported)",
|
||||
Offset, HeaderData.AddrSize);
|
||||
if (HeaderData.SegSize != 0)
|
||||
return createStringError(errc::not_supported,
|
||||
"non-zero segment selector size in address range "
|
||||
"table at offset 0x%" PRIx64 " is not supported",
|
||||
Offset);
|
||||
|
||||
// The first tuple following the header in each set begins at an offset
|
||||
// that is a multiple of the size of a single tuple (that is, twice the
|
||||
// size of an address). The header is padded, if necessary, to the
|
||||
// appropriate boundary.
|
||||
const uint32_t header_size = *offset_ptr - Offset;
|
||||
// The first tuple following the header in each set begins at an offset that
|
||||
// is a multiple of the size of a single tuple (that is, twice the size of
|
||||
// an address because we do not support non-zero segment selector sizes).
|
||||
// Therefore, the full length should also be a multiple of the tuple size.
|
||||
const uint32_t tuple_size = HeaderData.AddrSize * 2;
|
||||
if (full_length % tuple_size != 0)
|
||||
return createStringError(
|
||||
errc::invalid_argument,
|
||||
"address range table at offset 0x%" PRIx64
|
||||
" has length that is not a multiple of the tuple size",
|
||||
Offset);
|
||||
|
||||
// The header is padded, if necessary, to the appropriate boundary.
|
||||
const uint32_t header_size = *offset_ptr - Offset;
|
||||
uint32_t first_tuple_offset = 0;
|
||||
while (first_tuple_offset < header_size)
|
||||
first_tuple_offset += tuple_size;
|
||||
|
||||
// There should be space for at least one tuple.
|
||||
if (full_length <= first_tuple_offset)
|
||||
return createStringError(
|
||||
errc::invalid_argument,
|
||||
"address range table at offset 0x%" PRIx64
|
||||
" has an insufficient length to contain any entries",
|
||||
Offset);
|
||||
|
||||
*offset_ptr = Offset + first_tuple_offset;
|
||||
|
||||
Descriptor arangeDescriptor;
|
||||
@ -111,14 +154,23 @@ Error DWARFDebugArangeSet::extract(DataExtractor data, uint64_t *offset_ptr) {
|
||||
"Different datatypes for addresses and sizes!");
|
||||
assert(sizeof(arangeDescriptor.Address) >= HeaderData.AddrSize);
|
||||
|
||||
while (data.isValidOffset(*offset_ptr)) {
|
||||
uint64_t end_offset = Offset + full_length;
|
||||
while (*offset_ptr < end_offset) {
|
||||
arangeDescriptor.Address = data.getUnsigned(offset_ptr, HeaderData.AddrSize);
|
||||
arangeDescriptor.Length = data.getUnsigned(offset_ptr, HeaderData.AddrSize);
|
||||
|
||||
// Each set of tuples is terminated by a 0 for the address and 0
|
||||
// for the length.
|
||||
if (arangeDescriptor.Address == 0 && arangeDescriptor.Length == 0)
|
||||
return ErrorSuccess();
|
||||
if (arangeDescriptor.Length == 0) {
|
||||
// Each set of tuples is terminated by a 0 for the address and 0
|
||||
// for the length.
|
||||
if (arangeDescriptor.Address == 0 && *offset_ptr == end_offset)
|
||||
return ErrorSuccess();
|
||||
return createStringError(
|
||||
errc::invalid_argument,
|
||||
"address range table at offset 0x%" PRIx64
|
||||
" has an invalid tuple (length = 0) at offset 0x%" PRIx64,
|
||||
Offset, *offset_ptr - tuple_size);
|
||||
}
|
||||
|
||||
ArangeDescriptors.push_back(arangeDescriptor);
|
||||
}
|
||||
|
||||
|
@ -73,6 +73,23 @@ TEST(DWARFDebugArangeSet, UnsupportedAddressSize) {
|
||||
"(4 and 8 supported)");
|
||||
}
|
||||
|
||||
TEST(DWARFDebugArangeSet, UnsupportedSegmentSelectorSize) {
|
||||
static const char DebugArangesSecRaw[] =
|
||||
"\x14\x00\x00\x00" // Length
|
||||
"\x02\x00" // Version
|
||||
"\x00\x00\x00\x00" // Debug Info Offset
|
||||
"\x04" // Address Size
|
||||
"\x04" // Segment Selector Size (not supported)
|
||||
// No padding
|
||||
"\x00\x00\x00\x00" // Termination tuple
|
||||
"\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00";
|
||||
ExpectExtractError(
|
||||
DebugArangesSecRaw,
|
||||
"non-zero segment selector size in address range table at offset 0x0 "
|
||||
"is not supported");
|
||||
}
|
||||
|
||||
TEST(DWARFDebugArangeSet, NoTerminationEntry) {
|
||||
static const char DebugArangesSecRaw[] =
|
||||
"\x14\x00\x00\x00" // Length
|
||||
@ -90,7 +107,9 @@ TEST(DWARFDebugArangeSet, NoTerminationEntry) {
|
||||
}
|
||||
|
||||
TEST(DWARFDebugArangeSet, ReservedUnitLength) {
|
||||
static const char DebugArangesSecRaw[] =
|
||||
// Note: 12 is the minimum length to pass the basic check for the size of
|
||||
// the section. 1 will be automatically subtracted in ExpectExtractError().
|
||||
static const char DebugArangesSecRaw[12 + 1] =
|
||||
"\xf0\xff\xff\xff"; // Reserved unit length value
|
||||
ExpectExtractError(
|
||||
DebugArangesSecRaw,
|
||||
@ -98,4 +117,76 @@ TEST(DWARFDebugArangeSet, ReservedUnitLength) {
|
||||
"of value 0xfffffff0");
|
||||
}
|
||||
|
||||
TEST(DWARFDebugArangeSet, SectionTooShort) {
|
||||
// Note: 1 will be automatically subtracted in ExpectExtractError().
|
||||
static const char DebugArangesSecRaw[11 + 1] = {0};
|
||||
ExpectExtractError(
|
||||
DebugArangesSecRaw,
|
||||
"section is not large enough to contain an address range table "
|
||||
"at offset 0x0");
|
||||
}
|
||||
|
||||
TEST(DWARFDebugArangeSet, SectionTooShortDWARF64) {
|
||||
// Note: 1 will be automatically subtracted in ExpectExtractError().
|
||||
static const char DebugArangesSecRaw[23 + 1] =
|
||||
"\xff\xff\xff\xff"; // DWARF64 mark
|
||||
ExpectExtractError(
|
||||
DebugArangesSecRaw,
|
||||
"section is not large enough to contain a DWARF64 address range table "
|
||||
"at offset 0x0");
|
||||
}
|
||||
|
||||
TEST(DWARFDebugArangeSet, NoSpaceForEntries) {
|
||||
static const char DebugArangesSecRaw[] =
|
||||
"\x0c\x00\x00\x00" // Length
|
||||
"\x02\x00" // Version
|
||||
"\x00\x00\x00\x00" // Debug Info Offset
|
||||
"\x04" // Address Size
|
||||
"\x00" // Segment Selector Size
|
||||
"\x00\x00\x00\x00" // Padding
|
||||
; // No entries
|
||||
ExpectExtractError(
|
||||
DebugArangesSecRaw,
|
||||
"address range table at offset 0x0 has an insufficient length "
|
||||
"to contain any entries");
|
||||
}
|
||||
|
||||
TEST(DWARFDebugArangeSet, UnevenLength) {
|
||||
static const char DebugArangesSecRaw[] =
|
||||
"\x1b\x00\x00\x00" // Length (not a multiple of tuple size)
|
||||
"\x02\x00" // Version
|
||||
"\x00\x00\x00\x00" // Debug Info Offset
|
||||
"\x04" // Address Size
|
||||
"\x00" // Segment Selector Size
|
||||
"\x00\x00\x00\x00" // Padding
|
||||
"\x00\x00\x00\x00" // Entry: Address
|
||||
"\x01\x00\x00\x00" // Length
|
||||
"\x00\x00\x00\x00" // Termination tuple
|
||||
"\x00\x00\x00\x00";
|
||||
ExpectExtractError(
|
||||
DebugArangesSecRaw,
|
||||
"address range table at offset 0x0 has length that is not a multiple "
|
||||
"of the tuple size");
|
||||
}
|
||||
|
||||
TEST(DWARFDebugArangeSet, ZeroLengthEntry) {
|
||||
static const char DebugArangesSecRaw[] =
|
||||
"\x24\x00\x00\x00" // Length
|
||||
"\x02\x00" // Version
|
||||
"\x00\x00\x00\x00" // Debug Info Offset
|
||||
"\x04" // Address Size
|
||||
"\x00" // Segment Selector Size
|
||||
"\x00\x00\x00\x00" // Padding
|
||||
"\x00\x00\x00\x00" // Entry1: Address
|
||||
"\x01\x00\x00\x00" // Length
|
||||
"\x01\x00\x00\x00" // Entry2: Address
|
||||
"\x00\x00\x00\x00" // Length (invalid)
|
||||
"\x00\x00\x00\x00" // Termination tuple
|
||||
"\x00\x00\x00\x00";
|
||||
ExpectExtractError(
|
||||
DebugArangesSecRaw,
|
||||
"address range table at offset 0x0 has an invalid tuple (length = 0) "
|
||||
"at offset 0x18");
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
Loading…
Reference in New Issue
Block a user