[DebugInfo] Avoid an infinite loop with a truncated pre-v5 .debug_str_offsets.dwo.
authorIgor Kudrin <ikudrin@accesssoftek.com>
Fri, 14 Aug 2020 06:11:37 +0000 (13:11 +0700)
committerIgor Kudrin <ikudrin@accesssoftek.com>
Fri, 14 Aug 2020 06:11:37 +0000 (13:11 +0700)
dumpStringOffsetsSection() expects the size of a contribution to be
correctly aligned. The patch adds the corresponding verifications for
pre-v5 cases.

Differential Revision: https://reviews.llvm.org/D85739

llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-invalid.s [new file with mode: 0644]

index a6d44f0..0527f29 100644 (file)
@@ -995,11 +995,17 @@ DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) {
   // Prior to DWARF v5, we derive the contribution size from the
   // index table (in a package file). In a .dwo file it is simply
   // the length of the string offsets section.
-  if (!IndexEntry)
-    return {Optional<StrOffsetsContributionDescriptor>(
-        {0, StringOffsetSection.Data.size(), 4, Header.getFormat()})};
+  StrOffsetsContributionDescriptor Desc;
   if (C)
-    return {Optional<StrOffsetsContributionDescriptor>(
-        {C->Offset, C->Length, 4, Header.getFormat()})};
-  return None;
+    Desc = StrOffsetsContributionDescriptor(C->Offset, C->Length, 4,
+                                            Header.getFormat());
+  else if (!IndexEntry && !StringOffsetSection.Data.empty())
+    Desc = StrOffsetsContributionDescriptor(0, StringOffsetSection.Data.size(),
+                                            4, Header.getFormat());
+  else
+    return None;
+  auto DescOrError = Desc.validateContributionSize(DA);
+  if (!DescOrError)
+    return DescOrError.takeError();
+  return *DescOrError;
 }
diff --git a/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-invalid.s b/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-v4-invalid.s
new file mode 100644 (file)
index 0000000..e8e084c
--- /dev/null
@@ -0,0 +1,65 @@
+## This tests handling invalid .debug_str_offsets.dwo sections in
+## a pre-standard DWO/DWP file.
+
+# RUN: llvm-mc -triple x86_64 %s -filetype=obj -o %t.dwo
+# RUN: not llvm-dwarfdump -v %t.dwo 2>&1 | FileCheck %s
+
+# RUN: llvm-mc -triple x86_64 %s -filetype=obj -o %t.dwp --defsym DWP=0
+# RUN: not llvm-dwarfdump -v %t.dwp 2>&1 | FileCheck %s
+
+# CHECK: error: invalid reference to or invalid content in .debug_str_offsets[.dwo]: length exceeds section size
+
+    .section .debug_abbrev.dwo,"e",@progbits
+.LAbbr:
+    .byte 0x01  # Abbrev code
+    .byte 0x11  # DW_TAG_compile_unit
+    .byte 0x00  # DW_CHILDREN_no
+    .byte 0x00  # EOM(1)
+    .byte 0x00  # EOM(2)
+    .byte 0x00  # EOM(3)
+.LAbbrEnd:
+
+    .section .debug_info.dwo,"e",@progbits
+.LCU:
+    .long .LCUEnd-.LCUVersion
+.LCUVersion:
+    .short 4
+    .long 0
+    .byte 8
+    .uleb128 1
+.LCUEnd:
+
+## The section is truncated, i.e. its size is not a multiple of entry size.
+    .section .debug_str_offsets.dwo,"e",@progbits
+.LStrOff:
+    .byte 0
+.LStrOffEnd:
+
+.ifdef DWP
+    .section .debug_cu_index, "", @progbits
+## Header:
+    .long 2                         # Version
+    .long 3                         # Section count
+    .long 1                         # Unit count
+    .long 2                         # Slot count
+## Hash Table of Signatures:
+    .quad 0x1100001122222222        # DWO Id of CU0
+    .quad 0
+## Parallel Table of Indexes:
+    .long 1
+    .long 0
+## Table of Section Offsets:
+## Row 0:
+    .long 1                         # DW_SECT_INFO
+    .long 3                         # DW_SECT_ABBREV
+    .long 6                         # DW_SECT_STR_OFFSETS
+## Row 1, offsets of the contribution
+    .long .LCU-.debug_info.dwo
+    .long .LAbbr-.debug_abbrev.dwo
+    .long .LStrOff-.debug_str_offsets.dwo
+## Table of Section Sizes:
+## Row 1, sizes of the contribution
+    .long .LCUEnd-.LCU
+    .long .LAbbrEnd-.LAbbr
+    .long .LStrOffEnd-.LStrOff
+.endif