Skip to content

Commit

Permalink
[DebugInfo] Fix infinite loop caused by reading past debug_line end
Browse files Browse the repository at this point in the history
If the claimed unit length of a debug line program is such that the line
table would finish past the end of the .debug_line section, an infinite
loop occurs because the data extractor will continue to "read" zeroes
without changing the offset. This previously didn't hit an error because
the line table program handles a series of zeroes as a bad extended
opcode.

This patch fixes the inifinite loop and adds a warning if the program
doesn't fit in the available data.

Reviewed by: JDevlieghere

Differential Revision: https://reviews.llvm.org/D72279
  • Loading branch information
jh7370 committed Jan 7, 2020
1 parent 051c4d5 commit 216796f
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
19 changes: 17 additions & 2 deletions llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
Expand Up @@ -528,8 +528,23 @@ Error DWARFDebugLine::LineTable::parse(
if (PrologueErr)
return PrologueErr;

const uint64_t EndOffset =
DebugLineOffset + Prologue.TotalLength + Prologue.sizeofTotalLength();
uint64_t ProgramLength = Prologue.TotalLength + Prologue.sizeofTotalLength();
if (!DebugLineData.isValidOffsetForDataOfSize(DebugLineOffset,
ProgramLength)) {
assert(DebugLineData.size() > DebugLineOffset &&
"prologue parsing should handle invalid offset");
uint64_t BytesRemaining = DebugLineData.size() - DebugLineOffset;
RecoverableErrorCallback(
createStringError(errc::invalid_argument,
"line table program with offset 0x%8.8" PRIx64
" has length 0x%8.8" PRIx64 " but only 0x%8.8" PRIx64
" bytes are available",
DebugLineOffset, ProgramLength, BytesRemaining));
// Continue by capping the length at the number of remaining bytes.
ProgramLength = BytesRemaining;
}

const uint64_t EndOffset = DebugLineOffset + ProgramLength;

// See if we should tell the data extractor the address size.
if (DebugLineData.getAddressSize() == 0)
Expand Down
29 changes: 29 additions & 0 deletions llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
Expand Up @@ -438,6 +438,35 @@ TEST_F(DebugLineBasicFixture, ErrorForInvalidExtendedOpcodeLength) {
"0x00000030 expected 0x02 found 0x01");
}

TEST_F(DebugLineBasicFixture, ErrorForUnitLengthTooLarge) {
if (!setupGenerator())
return;

LineTable &Padding = Gen->addLineTable();
// Add some padding to show that a non-zero offset is handled correctly.
Padding.setCustomPrologue({{0, LineTable::Byte}});
LineTable &LT = Gen->addLineTable();
LT.addStandardOpcode(DW_LNS_copy, {});
LT.addStandardOpcode(DW_LNS_const_add_pc, {});
LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
// Set the total length to 1 higher than the actual length. The program body
// has size 5.
Prologue.TotalLength += 6;
LT.setPrologue(Prologue);

generate();

auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 1, *Context,
nullptr, RecordRecoverable);
checkError("line table program with offset 0x00000001 has length 0x00000034 "
"but only 0x00000033 bytes are available",
std::move(Recoverable));
ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 2u);
EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);
}

TEST_F(DebugLineBasicFixture, ErrorForMismatchedAddressSize) {
if (!setupGenerator())
return;
Expand Down

0 comments on commit 216796f

Please sign in to comment.