mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-19 11:35:51 -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 segment selectors are omitted from all tuples, including
|
||||||
// the terminating tuple.
|
// 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;
|
dwarf::DwarfFormat format = dwarf::DWARF32;
|
||||||
HeaderData.Length = data.getU32(offset_ptr);
|
HeaderData.Length = data.getU32(offset_ptr);
|
||||||
if (HeaderData.Length == dwarf::DW_LENGTH_DWARF64) {
|
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);
|
HeaderData.Length = data.getU64(offset_ptr);
|
||||||
format = dwarf::DWARF64;
|
format = dwarf::DWARF64;
|
||||||
} else if (HeaderData.Length >= dwarf::DW_LENGTH_lo_reserved) {
|
} 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 "
|
" has unsupported address size: %d "
|
||||||
"(4 and 8 supported)",
|
"(4 and 8 supported)",
|
||||||
Offset, HeaderData.AddrSize);
|
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
|
// The first tuple following the header in each set begins at an offset that
|
||||||
// that is a multiple of the size of a single tuple (that is, twice the
|
// is a multiple of the size of a single tuple (that is, twice the size of
|
||||||
// size of an address). The header is padded, if necessary, to the
|
// an address because we do not support non-zero segment selector sizes).
|
||||||
// appropriate boundary.
|
// Therefore, the full length should also be a multiple of the tuple size.
|
||||||
const uint32_t header_size = *offset_ptr - Offset;
|
|
||||||
const uint32_t tuple_size = HeaderData.AddrSize * 2;
|
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;
|
uint32_t first_tuple_offset = 0;
|
||||||
while (first_tuple_offset < header_size)
|
while (first_tuple_offset < header_size)
|
||||||
first_tuple_offset += tuple_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;
|
*offset_ptr = Offset + first_tuple_offset;
|
||||||
|
|
||||||
Descriptor arangeDescriptor;
|
Descriptor arangeDescriptor;
|
||||||
@ -111,14 +154,23 @@ Error DWARFDebugArangeSet::extract(DataExtractor data, uint64_t *offset_ptr) {
|
|||||||
"Different datatypes for addresses and sizes!");
|
"Different datatypes for addresses and sizes!");
|
||||||
assert(sizeof(arangeDescriptor.Address) >= HeaderData.AddrSize);
|
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.Address = data.getUnsigned(offset_ptr, HeaderData.AddrSize);
|
||||||
arangeDescriptor.Length = 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
|
if (arangeDescriptor.Length == 0) {
|
||||||
// for the length.
|
// Each set of tuples is terminated by a 0 for the address and 0
|
||||||
if (arangeDescriptor.Address == 0 && arangeDescriptor.Length == 0)
|
// for the length.
|
||||||
return ErrorSuccess();
|
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);
|
ArangeDescriptors.push_back(arangeDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +73,23 @@ TEST(DWARFDebugArangeSet, UnsupportedAddressSize) {
|
|||||||
"(4 and 8 supported)");
|
"(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) {
|
TEST(DWARFDebugArangeSet, NoTerminationEntry) {
|
||||||
static const char DebugArangesSecRaw[] =
|
static const char DebugArangesSecRaw[] =
|
||||||
"\x14\x00\x00\x00" // Length
|
"\x14\x00\x00\x00" // Length
|
||||||
@ -90,7 +107,9 @@ TEST(DWARFDebugArangeSet, NoTerminationEntry) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(DWARFDebugArangeSet, ReservedUnitLength) {
|
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
|
"\xf0\xff\xff\xff"; // Reserved unit length value
|
||||||
ExpectExtractError(
|
ExpectExtractError(
|
||||||
DebugArangesSecRaw,
|
DebugArangesSecRaw,
|
||||||
@ -98,4 +117,76 @@ TEST(DWARFDebugArangeSet, ReservedUnitLength) {
|
|||||||
"of value 0xfffffff0");
|
"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
|
} // end anonymous namespace
|
||||||
|
Loading…
Reference in New Issue
Block a user