[PATCH] D72279: [DebugInfo] Fix infinite loop caused by reading past debug_line end

James Henderson via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 6 08:44:07 PST 2020


jhenderson created this revision.
jhenderson added reviewers: MaskRay, ikudrin, dblaikie, JDevlieghere, probinson.
Herald added a subscriber: hiraditya.
Herald added a project: LLVM.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D72279

Files:
  llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
  llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp


Index: llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
===================================================================
--- llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
+++ 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 &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(4, 8))
     return;
Index: llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
===================================================================
--- llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
+++ 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)


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D72279.236386.patch
Type: text/x-patch
Size: 3093 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200106/78dbdde2/attachment.bin>


More information about the llvm-commits mailing list