diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp @@ -377,56 +377,36 @@ Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS, uint64_t *Offset) { - uint64_t StartingOffset = *Offset; - // Check that we can read the unit length field. - if (!AS.isValidOffsetForDataOfSize(StartingOffset, 4)) + auto HeaderError = [Offset = *Offset](Error E) { return createStringError(errc::illegal_byte_sequence, - "Section too small: cannot read header."); - UnitLength = AS.getU32(Offset); - if (UnitLength >= dwarf::DW_LENGTH_lo_reserved && - UnitLength != dwarf::DW_LENGTH_DWARF64) - return createStringError(errc::illegal_byte_sequence, - "Unsupported reserved unit length value"); - Format = (UnitLength == dwarf::DW_LENGTH_DWARF64) ? dwarf::DWARF64 - : dwarf::DWARF32; - - // These fields are the same for 32-bit and 64-bit DWARF formats. - constexpr unsigned CommonHeaderSize = 2 + // Version - 2 + // Padding - 4 + // CU count - 4 + // Local TU count - 4 + // Foreign TU count - 4 + // Bucket count - 4 + // Name count - 4 + // Abbreviations table size - 4; // Augmentation string size - // Check that we can read the fixed-size part. - if (!AS.isValidOffsetForDataOfSize( - StartingOffset, - CommonHeaderSize + dwarf::getUnitLengthFieldByteSize(Format))) - return createStringError(errc::illegal_byte_sequence, - "Section too small: cannot read header."); - if (Format == dwarf::DWARF64) - UnitLength = AS.getU64(Offset); - Version = AS.getU16(Offset); - // Skip padding - *Offset += 2; - CompUnitCount = AS.getU32(Offset); - LocalTypeUnitCount = AS.getU32(Offset); - ForeignTypeUnitCount = AS.getU32(Offset); - BucketCount = AS.getU32(Offset); - NameCount = AS.getU32(Offset); - AbbrevTableSize = AS.getU32(Offset); - AugmentationStringSize = alignTo(AS.getU32(Offset), 4); - - if (!AS.isValidOffsetForDataOfSize(*Offset, AugmentationStringSize)) - return createStringError( - errc::illegal_byte_sequence, - "Section too small: cannot read header augmentation."); + "parsing .debug_names header at 0x%" PRIx64 ": %s", + Offset, toString(std::move(E)).c_str()); + }; + + DataExtractor::Cursor C(*Offset); + std::tie(UnitLength, Format) = AS.getInitialLength(C); + + Version = AS.getU16(C); + AS.skip(C, 2); // padding + CompUnitCount = AS.getU32(C); + LocalTypeUnitCount = AS.getU32(C); + ForeignTypeUnitCount = AS.getU32(C); + BucketCount = AS.getU32(C); + NameCount = AS.getU32(C); + AbbrevTableSize = AS.getU32(C); + AugmentationStringSize = alignTo(AS.getU32(C), 4); + + if (!C) + return HeaderError(C.takeError()); + + if (!AS.isValidOffsetForDataOfSize(C.tell(), AugmentationStringSize)) + return HeaderError(createStringError(errc::illegal_byte_sequence, + "cannot read header augmentation")); AugmentationString.resize(AugmentationStringSize); - AS.getU8(Offset, reinterpret_cast(AugmentationString.data()), + AS.getU8(C, reinterpret_cast(AugmentationString.data()), AugmentationStringSize); - return Error::success(); + *Offset = C.tell(); + return C.takeError(); } void DWARFDebugNames::Abbrev::dump(ScopedPrinter &W) const { diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug-names-verify-short1.s b/llvm/test/tools/llvm-dwarfdump/X86/debug-names-verify-short1.s --- a/llvm/test/tools/llvm-dwarfdump/X86/debug-names-verify-short1.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug-names-verify-short1.s @@ -1,7 +1,7 @@ # RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj | \ # RUN: not llvm-dwarfdump -verify - | FileCheck %s -# CHECK: Section too small: cannot read header. +# CHECK: parsing .debug_names header at 0x0: unexpected end of data at offset 0x20 .section .debug_str,"MS",@progbits,1 .Lstring_producer: diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug-names-verify-short2.s b/llvm/test/tools/llvm-dwarfdump/X86/debug-names-verify-short2.s --- a/llvm/test/tools/llvm-dwarfdump/X86/debug-names-verify-short2.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug-names-verify-short2.s @@ -1,7 +1,7 @@ # RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj | \ # RUN: not llvm-dwarfdump -verify - | FileCheck %s -# CHECK: Section too small: cannot read header augmentation. +# CHECK: parsing .debug_names header at 0x0: cannot read header augmentation .section .debug_str,"MS",@progbits,1 .Lstring_producer: diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp --- a/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFAcceleratorTableTest.cpp @@ -8,45 +8,42 @@ #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/Testing/Support/Error.h" #include "gtest/gtest.h" using namespace llvm; -namespace { - -void ExpectDebugNamesExtractError(StringRef NamesSecData, StringRef StrSecData, - const char *ErrorMessage) { - DWARFSection NamesDWARFSection; - NamesDWARFSection.Data = NamesSecData; - StringMap> Sections; - auto Context = DWARFContext::create(Sections, /* AddrSize = */ 4, - /* isLittleEndian = */ true); - DWARFDataExtractor NamesExtractor(Context->getDWARFObj(), NamesDWARFSection, - /* isLittleEndian = */ true, - /* AddrSize = */ 4); +static Error ExtractDebugNames(StringRef NamesSecData, StringRef StrSecData) { + DWARFDataExtractor NamesExtractor(NamesSecData, + /*isLittleEndian=*/true, + /*AddrSize=*/4); DataExtractor StrExtractor(StrSecData, - /* isLittleEndian = */ true, - /* AddrSize = */ 4); + /*isLittleEndian=*/true, + /*AddrSize=*/4); DWARFDebugNames Table(NamesExtractor, StrExtractor); - Error E = Table.extract(); - ASSERT_TRUE(E.operator bool()); - EXPECT_STREQ(ErrorMessage, toString(std::move(E)).c_str()); + return Table.extract(); } +namespace { + TEST(DWARFDebugNames, ReservedUnitLength) { static const char NamesSecData[64] = "\xf0\xff\xff\xff"; // Reserved unit length value - ExpectDebugNamesExtractError(StringRef(NamesSecData, sizeof(NamesSecData)), - StringRef(), - "Unsupported reserved unit length value"); + EXPECT_THAT_ERROR( + ExtractDebugNames(StringRef(NamesSecData, sizeof(NamesSecData)), + StringRef()), + FailedWithMessage("parsing .debug_names header at 0x0: unsupported " + "reserved unit length of value 0xfffffff0")); } TEST(DWARFDebugNames, TooSmallForDWARF64) { // DWARF64 header takes at least 44 bytes. static const char NamesSecData[43] = "\xff\xff\xff\xff"; // DWARF64 mark - ExpectDebugNamesExtractError( - StringRef(NamesSecData, sizeof(NamesSecData)), StringRef(), - "Section too small: cannot read header."); + EXPECT_THAT_ERROR( + ExtractDebugNames(StringRef(NamesSecData, sizeof(NamesSecData)), + StringRef()), + FailedWithMessage("parsing .debug_names header at 0x0: unexpected end of " + "data at offset 0x28")); } } // end anonymous namespace