diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -539,8 +539,23 @@ 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) diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp @@ -513,6 +513,35 @@ EXPECT_EQ((*ExpectedLineTable)->Rows[2].IsStmt, 1u); } +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 < = 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(4, 8)) return;