[llvm] 1dc62d0 - [DebugInfo][test] Replace pre-canned binary test

James Henderson via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 10 06:00:42 PST 2020


Author: James Henderson
Date: 2020-02-10T13:54:40Z
New Revision: 1dc62d0358c89d3e5db970e62723fa8b0b0c56e3

URL: https://github.com/llvm/llvm-project/commit/1dc62d0358c89d3e5db970e62723fa8b0b0c56e3
DIFF: https://github.com/llvm/llvm-project/commit/1dc62d0358c89d3e5db970e62723fa8b0b0c56e3.diff

LOG: [DebugInfo][test] Replace pre-canned binary test

The DebugInfo/dwarfdump-invalid-line-table test used a pre-canned binary
generated by a fuzzer to demonstrate a bug fix. Unfortunately, the
binary is rigid and requires hand-editing if we change behaviour, such
as rejecting certain properties within it (as I plan on doing in another
change).

Rather than hand-edit the binary, I have replaced it with two tests. The
first tests the high-level code path from the debug line parser that
produces the same error as this test previously did, and the second is a
set of unit test cases that comprehensively cover the
FormValue::skipValue method, which in turn covers the area that the
original bug fix touched.

Reviewed by: MaskRay, dblaikie

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

Added: 
    

Modified: 
    llvm/test/tools/llvm-dwarfdump/X86/Inputs/debug_line_malformed.s
    llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test
    llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp

Removed: 
    llvm/test/DebugInfo/Inputs/invalid.linetable
    llvm/test/DebugInfo/dwarfdump-invalid-line-table.test


################################################################################
diff  --git a/llvm/test/DebugInfo/Inputs/invalid.linetable b/llvm/test/DebugInfo/Inputs/invalid.linetable
deleted file mode 100644
index 5df41391afa6..000000000000
Binary files a/llvm/test/DebugInfo/Inputs/invalid.linetable and /dev/null 
diff er

diff  --git a/llvm/test/DebugInfo/dwarfdump-invalid-line-table.test b/llvm/test/DebugInfo/dwarfdump-invalid-line-table.test
deleted file mode 100644
index afcaec003064..000000000000
--- a/llvm/test/DebugInfo/dwarfdump-invalid-line-table.test
+++ /dev/null
@@ -1,5 +0,0 @@
-Verify that dwarfdump doesn't crash on invalid line table prologue.
-OSS-Fuzz Issue 4644 (https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=4644)
-
-RUN: llvm-dwarfdump --verbose %p/Inputs/invalid.linetable 2>&1 | FileCheck %s --check-prefix=INVALID-LINE-TABLE
-INVALID-LINE-TABLE: invalid directory or file table description

diff  --git a/llvm/test/tools/llvm-dwarfdump/X86/Inputs/debug_line_malformed.s b/llvm/test/tools/llvm-dwarfdump/X86/Inputs/debug_line_malformed.s
index 913ec625caf4..e01ed9a5bfae 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/Inputs/debug_line_malformed.s
+++ b/llvm/test/tools/llvm-dwarfdump/X86/Inputs/debug_line_malformed.s
@@ -383,6 +383,46 @@
 .byte   0, 1, 1         # DW_LNE_end_sequence
 .Linvalid_md5_end1:
 
+# V5 invalid directory content description has unsupported form.
+.long   .Linvalid_dir_form_end0-.Linvalid_dir_form_start0   # Length of Unit
+.Linvalid_dir_form_start0:
+.short  5               # DWARF version number
+.byte   8               # Address Size
+.byte   0               # Segment Selector Size
+.long   .Linvalid_dir_form_header_end0 - .Linvalid_dir_form_params0
+.Linvalid_dir_form_params0:
+.byte   1               # Minimum Instruction Length
+.byte   1               # Maximum Operations per Instruction
+.byte   1               # Default is_stmt
+.byte   -5              # Line Base
+.byte   14              # Line Range
+.byte   13              # Opcode Base
+.byte   0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 # Standard Opcode Lengths
+# Directory table format
+.byte   2               # Two elements per directory entry
+.byte   1               # DW_LNCT_path
+.byte   0x08            # DW_FORM_string
+.byte   2               # DW_LNCT_directory_index (ignored)
+.byte   0x7f            # Unknown form
+# Directory table entries
+.byte   2               # 2 directories
+.asciz  "/foo"          # Directory name
+.byte   0xff            # Arbitrary data for unknown form
+.asciz  "/bar"          # Directory name
+.byte   0xff            # Arbitrary data for unknown form
+# File table format
+.byte   1               # 1 element per file entry
+.byte   1               # DW_LNCT_path
+.byte   0x08            # DW_FORM_string
+# File table entries
+.byte   1               # 1 file
+.asciz  "xyz"           # File names
+.Linvalid_dir_form_header_end0:
+.byte   0, 9, 2         # DW_LNE_set_address
+.quad   0xaaaabbbbccccdddd
+.byte   0, 1, 1         # DW_LNE_end_sequence
+.Linvalid_dir_form_end0:
+
 # Trailing good section.
 .long   .Lunit_good_end - .Lunit_good_start # Length of Unit (DWARF-32 format)
 .Lunit_good_start:

diff  --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test b/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test
index 45bd52cb6e46..73efb39cbdb3 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test
@@ -36,7 +36,7 @@
 # RUN: FileCheck %s --input-file=%t-malformed-off-first.err --check-prefix=ALL
 
 ## Don't stop looking for the later unit if non-fatal issues are found.
-# RUN: llvm-dwarfdump -debug-line=0x2ec %t-malformed.o 2> %t-malformed-off-last.err \
+# RUN: llvm-dwarfdump -debug-line=0x332 %t-malformed.o 2> %t-malformed-off-last.err \
 # RUN:   | FileCheck %s --check-prefix=LAST --implicit-check-not='debug_line[{{.*}}]'
 # RUN: FileCheck %s --input-file=%t-malformed-off-last.err --check-prefix=ALL
 
@@ -143,14 +143,22 @@
 
 ## Case 12: V5 invalid MD5 hash form when data beyond the prologue length has
 ## been read before the MD5 problem is identified.
-# NONFATAL: debug_line[0x000002ae]
+# NONFATAL:      debug_line[0x000002ae]
 # NONFATAL-NEXT: Line table prologue
 # NONFATAL:      include_directories[  0] = "/tmp"
 # NONFATAL-NOT:  file_names
 # NONFATAL:      0x0000000000000000 {{.*}} epilogue_begin
 # NONFATAL:      0x4321432143214321 {{.*}} is_stmt end_sequence
 
-# LAST:          debug_line[0x000002ec]
+## Case 13: V5 invalid directory content description has unsupported form.
+# NONFATAL:      debug_line[0x000002ec]
+# NONFATAL-NEXT: Line table prologue
+# NONFATAL:      include_directories[  0] = "/foo"
+# NONFATAL-NOT:  include_directories
+# NONFATAL-NOT:  file_names
+# NONFATAL:      0xaaaabbbbccccdddd {{.*}} is_stmt end_sequence
+
+# LAST:          debug_line[0x00000332]
 # LAST:          0x00000000cafebabe {{.*}} end_sequence
 
 # RESERVED: warning: parsing line table prologue at offset 0x00000048 unsupported reserved unit length found of value 0xfffffffe
@@ -173,4 +181,6 @@
 # ALL-NEXT: warning: parsing line table prologue at 0x000002ae found an invalid directory or file table description at 0x000002e0
 # ALL-NEXT: warning: failed to parse file entry because the MD5 hash is invalid
 # ALL-NEXT: warning: parsing line table prologue at 0x000002ae should have ended at 0x000002d9 but it ended at 0x000002e0
+# ALL-NEXT: warning: parsing line table prologue at 0x000002ec found an invalid directory or file table description at 0x00000315
+# ALL-NEXT: warning: failed to parse directory entry because skipping the form value failed.
 # ALL-NOT:  warning:

diff  --git a/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp
index 097c160bf46e..bc86d1763aec 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp
@@ -120,4 +120,182 @@ TEST(DWARFFormValue, SignedConstantForms) {
   EXPECT_EQ(memcmp(Str.data(), "000102030405060708090a0b0c0d0e0f", 32), 0);
 }
 
+using ParamType = std::tuple<Form, uint16_t, uint8_t, DwarfFormat,
+                             ArrayRef<uint8_t>, uint32_t, bool>;
+
+struct FormSkipValueFixtureBase : public testing::TestWithParam<ParamType> {
+  void SetUp() {
+    std::tie(Fm, Version, AddrSize, Dwarf, InitialData, ExpectedSkipped,
+             ExpectedResult) = GetParam();
+  }
+
+  void doSkipValueTest() {
+    SCOPED_TRACE("Inputs: Form = " + std::to_string(Fm) +
+                 ", Version = " + std::to_string(Version) +
+                 ", AddrSize = " + std::to_string(uint32_t(AddrSize)) +
+                 ", DwarfFormat = " + std::to_string(Dwarf));
+    std::vector<uint8_t> Buf(InitialData.data(),
+                             InitialData.data() + InitialData.size());
+    // The data extractor only adjusts the offset to the end of the buffer when
+    // attempting to read past the end, so the buffer must be bigger than the
+    // expected amount to be skipped to identify cases where more data than
+    // expected is skipped.
+    Buf.resize(ExpectedSkipped + 1);
+    DWARFDataExtractor Data(Buf, sys::IsLittleEndianHost, AddrSize);
+    uint64_t Offset = 0;
+    EXPECT_EQ(DWARFFormValue::skipValue(Fm, Data, &Offset,
+                                        {Version, AddrSize, Dwarf}),
+              ExpectedResult);
+    EXPECT_EQ(Offset, ExpectedSkipped);
+  }
+
+  Form Fm;
+  uint16_t Version;
+  uint8_t AddrSize;
+  DwarfFormat Dwarf;
+  ArrayRef<uint8_t> InitialData;
+  uint32_t ExpectedSkipped;
+  bool ExpectedResult;
+};
+
+const uint8_t LEBData[] = {0x80, 0x1};
+ArrayRef<uint8_t> SampleLEB(LEBData, sizeof(LEBData));
+const uint32_t SampleLength = 0x80;
+ArrayRef<uint8_t>
+SampleUnsigned(reinterpret_cast<const uint8_t *>(&SampleLength),
+               sizeof(SampleLength));
+const uint8_t StringData[] = "abcdef";
+ArrayRef<uint8_t> SampleString(StringData, sizeof(StringData));
+const uint8_t IndirectData8[] = {DW_FORM_data8};
+const uint8_t IndirectData16[] = {DW_FORM_data16};
+const uint8_t IndirectAddr[] = {DW_FORM_addr};
+const uint8_t IndirectIndirectData1[] = {DW_FORM_indirect, DW_FORM_data1};
+const uint8_t IndirectIndirectEnd[] = {DW_FORM_indirect};
+
+// Gtest's paramterised tests only allow a maximum of 50 cases, so split the
+// test into multiple identical parts to share the cases.
+struct FormSkipValueFixture1 : FormSkipValueFixtureBase {};
+struct FormSkipValueFixture2 : FormSkipValueFixtureBase {};
+TEST_P(FormSkipValueFixture1, skipValuePart1) { doSkipValueTest(); }
+TEST_P(FormSkipValueFixture2, skipValuePart2) { doSkipValueTest(); }
+
+INSTANTIATE_TEST_CASE_P(
+    SkipValueTestParams1, FormSkipValueFixture1,
+    testing::Values(
+        // Form, Version, AddrSize, DwarfFormat, InitialData, ExpectedSize,
+        // ExpectedResult.
+        ParamType(DW_FORM_exprloc, 0, 0, DWARF32, SampleLEB,
+                  SampleLength + SampleLEB.size(), true),
+        ParamType(DW_FORM_block, 0, 0, DWARF32, SampleLEB,
+                  SampleLength + SampleLEB.size(), true),
+        ParamType(DW_FORM_block1, 0, 0, DWARF32, SampleUnsigned,
+                  SampleLength + 1, true),
+        ParamType(DW_FORM_block2, 0, 0, DWARF32, SampleUnsigned,
+                  SampleLength + 2, true),
+        ParamType(DW_FORM_block4, 0, 0, DWARF32, SampleUnsigned,
+                  SampleLength + 4, true),
+        ParamType(DW_FORM_string, 0, 0, DWARF32, SampleString,
+                  SampleString.size(), true),
+        ParamType(DW_FORM_addr, 0, 42, DWARF32, SampleUnsigned, 0, false),
+        ParamType(DW_FORM_addr, 4, 0, DWARF32, SampleUnsigned, 0, false),
+        ParamType(DW_FORM_addr, 4, 42, DWARF32, SampleUnsigned, 42, true),
+        ParamType(DW_FORM_ref_addr, 0, 1, DWARF32, SampleUnsigned, 0, false),
+        ParamType(DW_FORM_ref_addr, 1, 0, DWARF32, SampleUnsigned, 0, false),
+        ParamType(DW_FORM_ref_addr, 1, 1, DWARF32, SampleUnsigned, 4, true),
+        ParamType(DW_FORM_ref_addr, 1, 1, DWARF64, SampleUnsigned, 8, true),
+        ParamType(DW_FORM_ref_addr, 2, 42, DWARF32, SampleUnsigned, 42, true),
+        ParamType(DW_FORM_ref_addr, 2, 42, DWARF64, SampleUnsigned, 42, true),
+        ParamType(DW_FORM_ref_addr, 3, 3, DWARF32, SampleUnsigned, 4, true),
+        ParamType(DW_FORM_ref_addr, 3, 3, DWARF64, SampleUnsigned, 8, true),
+        ParamType(DW_FORM_flag_present, 4, 4, DWARF32, SampleUnsigned, 0, true),
+        ParamType(DW_FORM_data1, 0, 0, DWARF32, SampleUnsigned, 1, true),
+        ParamType(DW_FORM_data2, 0, 0, DWARF32, SampleUnsigned, 2, true),
+        ParamType(DW_FORM_data4, 0, 0, DWARF32, SampleUnsigned, 4, true),
+        ParamType(DW_FORM_data8, 0, 0, DWARF32, SampleUnsigned, 8, true),
+        ParamType(DW_FORM_data16, 0, 0, DWARF32, SampleUnsigned, 16, true),
+        ParamType(DW_FORM_flag, 0, 0, DWARF32, SampleUnsigned, 1, true),
+        ParamType(DW_FORM_ref1, 0, 0, DWARF32, SampleUnsigned, 1, true),
+        ParamType(DW_FORM_ref2, 0, 0, DWARF32, SampleUnsigned, 2, true),
+        ParamType(DW_FORM_ref4, 0, 0, DWARF32, SampleUnsigned, 4, true),
+        ParamType(DW_FORM_ref8, 0, 0, DWARF32, SampleUnsigned, 8, true),
+        ParamType(DW_FORM_ref_sig8, 0, 0, DWARF32, SampleUnsigned, 8, true),
+        ParamType(DW_FORM_ref_sup4, 0, 0, DWARF32, SampleUnsigned, 4, true),
+        ParamType(DW_FORM_ref_sup8, 0, 0, DWARF32, SampleUnsigned, 8, true),
+        ParamType(DW_FORM_strx1, 0, 0, DWARF32, SampleUnsigned, 1, true),
+        ParamType(DW_FORM_strx2, 0, 0, DWARF32, SampleUnsigned, 2, true),
+        ParamType(DW_FORM_strx4, 0, 0, DWARF32, SampleUnsigned, 4, true),
+        ParamType(DW_FORM_addrx1, 0, 0, DWARF32, SampleUnsigned, 1, true),
+        ParamType(DW_FORM_addrx2, 0, 0, DWARF32, SampleUnsigned, 2, true),
+        ParamType(DW_FORM_addrx4, 0, 0, DWARF32, SampleUnsigned, 4, true),
+        ParamType(DW_FORM_sec_offset, 0, 1, DWARF32, SampleUnsigned, 0, false),
+        ParamType(DW_FORM_sec_offset, 1, 0, DWARF32, SampleUnsigned, 0, false),
+        ParamType(DW_FORM_sec_offset, 1, 1, DWARF32, SampleUnsigned, 4, true),
+        ParamType(DW_FORM_sec_offset, 1, 1, DWARF64, SampleUnsigned, 8, true),
+        ParamType(DW_FORM_strp, 0, 1, DWARF32, SampleUnsigned, 0, false),
+        ParamType(DW_FORM_strp, 1, 0, DWARF32, SampleUnsigned, 0, false),
+        ParamType(DW_FORM_strp, 1, 1, DWARF32, SampleUnsigned, 4, true),
+        ParamType(DW_FORM_strp, 1, 1, DWARF64, SampleUnsigned, 8, true),
+        ParamType(DW_FORM_strp_sup, 0, 1, DWARF32, SampleUnsigned, 0, false),
+        ParamType(DW_FORM_strp_sup, 1, 0, DWARF32, SampleUnsigned, 0, false),
+        ParamType(DW_FORM_strp_sup, 1, 1, DWARF32, SampleUnsigned, 4, true),
+        ParamType(DW_FORM_strp_sup, 1, 1, DWARF64, SampleUnsigned, 8, true)), );
+
+INSTANTIATE_TEST_CASE_P(
+    SkipValueTestParams2, FormSkipValueFixture2,
+    testing::Values(
+        ParamType(DW_FORM_line_strp, 0, 1, DWARF32, SampleUnsigned, 0, false),
+        ParamType(DW_FORM_line_strp, 1, 0, DWARF32, SampleUnsigned, 0, false),
+        ParamType(DW_FORM_line_strp, 1, 1, DWARF32, SampleUnsigned, 4, true),
+        ParamType(DW_FORM_line_strp, 1, 1, DWARF64, SampleUnsigned, 8, true),
+        ParamType(DW_FORM_GNU_ref_alt, 0, 1, DWARF32, SampleUnsigned, 0, false),
+        ParamType(DW_FORM_GNU_ref_alt, 1, 0, DWARF32, SampleUnsigned, 0, false),
+        ParamType(DW_FORM_GNU_ref_alt, 1, 1, DWARF32, SampleUnsigned, 4, true),
+        ParamType(DW_FORM_GNU_ref_alt, 1, 1, DWARF64, SampleUnsigned, 8, true),
+        ParamType(DW_FORM_GNU_strp_alt, 0, 1, DWARF32, SampleUnsigned, 0,
+                  false),
+        ParamType(DW_FORM_GNU_strp_alt, 1, 0, DWARF32, SampleUnsigned, 0,
+                  false),
+        ParamType(DW_FORM_GNU_strp_alt, 1, 1, DWARF32, SampleUnsigned, 4, true),
+        ParamType(DW_FORM_GNU_strp_alt, 1, 1, DWARF64, SampleUnsigned, 8, true),
+        ParamType(DW_FORM_sdata, 0, 0, DWARF32, SampleLEB, SampleLEB.size(),
+                  true),
+        ParamType(DW_FORM_udata, 0, 0, DWARF32, SampleLEB, SampleLEB.size(),
+                  true),
+        ParamType(DW_FORM_ref_udata, 0, 0, DWARF32, SampleLEB, SampleLEB.size(),
+                  true),
+        ParamType(DW_FORM_strx, 0, 0, DWARF32, SampleLEB, SampleLEB.size(),
+                  true),
+        ParamType(DW_FORM_addrx, 0, 0, DWARF32, SampleLEB, SampleLEB.size(),
+                  true),
+        ParamType(DW_FORM_loclistx, 0, 0, DWARF32, SampleLEB, SampleLEB.size(),
+                  true),
+        ParamType(DW_FORM_rnglistx, 0, 0, DWARF32, SampleLEB, SampleLEB.size(),
+                  true),
+        ParamType(DW_FORM_GNU_addr_index, 0, 0, DWARF32, SampleLEB,
+                  SampleLEB.size(), true),
+        ParamType(DW_FORM_GNU_str_index, 0, 0, DWARF32, SampleLEB,
+                  SampleLEB.size(), true),
+        ParamType(DW_FORM_indirect, 0, 0, DWARF32,
+                  ArrayRef<uint8_t>(IndirectData8, sizeof(IndirectData8)), 9,
+                  true),
+        ParamType(DW_FORM_indirect, 0, 0, DWARF32,
+                  ArrayRef<uint8_t>(IndirectData16, sizeof(IndirectData16)), 17,
+                  true),
+        ParamType(DW_FORM_indirect, 4, 0, DWARF32,
+                  ArrayRef<uint8_t>(IndirectAddr, sizeof(IndirectAddr)), 1,
+                  false),
+        ParamType(DW_FORM_indirect, 4, 4, DWARF32,
+                  ArrayRef<uint8_t>(IndirectAddr, sizeof(IndirectAddr)), 5,
+                  true),
+        ParamType(DW_FORM_indirect, 4, 4, DWARF32,
+                  ArrayRef<uint8_t>(IndirectIndirectData1,
+                                    sizeof(IndirectIndirectData1)),
+                  3, true),
+        ParamType(DW_FORM_indirect, 4, 4, DWARF32,
+                  ArrayRef<uint8_t>(IndirectIndirectEnd,
+                                    sizeof(IndirectIndirectEnd)),
+                  2, false),
+        ParamType(/*Unknown=*/Form(0xff), 4, 4, DWARF32, SampleUnsigned, 0,
+                  false)), );
+
 } // end anonymous namespace


        


More information about the llvm-commits mailing list