[lld] 94935c0 - Re-apply "Revert "[DebugInfo] Add error checking around data extraction in DWARFAbbreviationDeclaration::extract""

Alex Langford via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 6 11:14:14 PDT 2023


Author: Alex Langford
Date: 2023-06-06T11:13:31-07:00
New Revision: 94935c0d9ac89263dd0d7ce6bfb6f700c0f10fa2

URL: https://github.com/llvm/llvm-project/commit/94935c0d9ac89263dd0d7ce6bfb6f700c0f10fa2
DIFF: https://github.com/llvm/llvm-project/commit/94935c0d9ac89263dd0d7ce6bfb6f700c0f10fa2.diff

LOG: Re-apply "Revert "[DebugInfo] Add error checking around data extraction in DWARFAbbreviationDeclaration::extract""

This reverts commit 11d61c079d4b4927efea42a38a27d4586887b764 to re-apply
6836a47b7e6b57927664ec6ec750ae37bb951129 with modifications.

Specifically, the errors in DWARFAbbreviationDeclaration::extract needed
to be moved as they are returned to ensure the right Error constructor
is selected.

Added: 
    

Modified: 
    lld/test/MachO/stabs-dwarf5.s
    lld/test/MachO/stabs-icf.s
    lld/test/MachO/stabs.s
    llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
    llvm/unittests/DebugInfo/DWARF/DWARFDebugAbbrevTest.cpp

Removed: 
    


################################################################################
diff  --git a/lld/test/MachO/stabs-dwarf5.s b/lld/test/MachO/stabs-dwarf5.s
index 61a0986e67d50..169f17987aab4 100644
--- a/lld/test/MachO/stabs-dwarf5.s
+++ b/lld/test/MachO/stabs-dwarf5.s
@@ -51,6 +51,8 @@ Lsection_abbrev:
   .byte  114                     ## DW_AT_str_offsets_base
   .byte  23                      ## DW_FORM_sec_offset
   .byte  0                       ## EOM(1)
+  .byte  0                       ## EOM(2)
+  .byte  0                       ## EOM(3)
 .section  __DWARF,__debug_info,regular,debug
 .set Lset0, Ldebug_info_end0-Ldebug_info_start0 ## Length of Unit
   .long  Lset0

diff  --git a/lld/test/MachO/stabs-icf.s b/lld/test/MachO/stabs-icf.s
index 129fc86663df2..99d0871ce4d2c 100644
--- a/lld/test/MachO/stabs-icf.s
+++ b/lld/test/MachO/stabs-icf.s
@@ -64,6 +64,8 @@ Lsection_abbrev:
   .byte  18                      ## DW_AT_high_pc
   .byte  6                       ## DW_FORM_data4
   .byte  0                       ## EOM(1)
+  .byte  0                       ## EOM(2)
+  .byte  0                       ## EOM(3)
 .section  __DWARF,__debug_info,regular,debug
 .set Lset0, Ldebug_info_end0-Ldebug_info_start0 ## Length of Unit
   .long  Lset0

diff  --git a/lld/test/MachO/stabs.s b/lld/test/MachO/stabs.s
index aa96f7c147a7e..145e7960b6657 100644
--- a/lld/test/MachO/stabs.s
+++ b/lld/test/MachO/stabs.s
@@ -205,6 +205,8 @@ Lsection_abbrev:
   .byte  18                      ## DW_AT_high_pc
   .byte  6                       ## DW_FORM_data4
   .byte  0                       ## EOM(1)
+  .byte  0                       ## EOM(2)
+  .byte  0                       ## EOM(3)
 .section  __DWARF,__debug_info,regular,debug
 .set Lset0, Ldebug_info_end0-Ldebug_info_start0 ## Length of Unit
   .long  Lset0
@@ -254,6 +256,8 @@ Lsection_abbrev:
   .byte  18                      ## DW_AT_high_pc
   .byte  6                       ## DW_FORM_data4
   .byte  0                       ## EOM(1)
+  .byte  0                       ## EOM(2)
+  .byte  0                       ## EOM(3)
 .section  __DWARF,__debug_info,regular,debug
 .set Lset0, Ldebug_info_end0-Ldebug_info_start0 ## Length of Unit
   .long  Lset0

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
index e131c42375ab5..ecdbd004efadb 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
@@ -38,18 +38,28 @@ llvm::Expected<DWARFAbbreviationDeclaration::ExtractState>
 DWARFAbbreviationDeclaration::extract(DataExtractor Data, uint64_t *OffsetPtr) {
   clear();
   const uint64_t Offset = *OffsetPtr;
-  Code = Data.getULEB128(OffsetPtr);
+  Error Err = Error::success();
+  Code = Data.getULEB128(OffsetPtr, &Err);
+  if (Err)
+    return std::move(Err);
+
   if (Code == 0)
     return ExtractState::Complete;
 
   CodeByteSize = *OffsetPtr - Offset;
-  Tag = static_cast<llvm::dwarf::Tag>(Data.getULEB128(OffsetPtr));
+  Tag = static_cast<llvm::dwarf::Tag>(Data.getULEB128(OffsetPtr, &Err));
+  if (Err)
+    return std::move(Err);
+
   if (Tag == DW_TAG_null) {
     clear();
     return make_error<llvm::object::GenericBinaryError>(
         "abbreviation declaration requires a non-null tag");
   }
-  uint8_t ChildrenByte = Data.getU8(OffsetPtr);
+  uint8_t ChildrenByte = Data.getU8(OffsetPtr, &Err);
+  if (Err)
+    return std::move(Err);
+
   HasChildren = (ChildrenByte == DW_CHILDREN_yes);
   // Assign a value to our optional FixedAttributeSize member variable. If
   // this member variable still has a value after the while loop below, then
@@ -58,8 +68,13 @@ DWARFAbbreviationDeclaration::extract(DataExtractor Data, uint64_t *OffsetPtr) {
 
   // Read all of the abbreviation attributes and forms.
   while (Data.isValidOffset(*OffsetPtr)) {
-    auto A = static_cast<Attribute>(Data.getULEB128(OffsetPtr));
-    auto F = static_cast<Form>(Data.getULEB128(OffsetPtr));
+    auto A = static_cast<Attribute>(Data.getULEB128(OffsetPtr, &Err));
+    if (Err)
+      return std::move(Err);
+
+    auto F = static_cast<Form>(Data.getULEB128(OffsetPtr, &Err));
+    if (Err)
+      return std::move(Err);
 
     // We successfully reached the end of this abbreviation declaration
     // since both attribute and form are zero. There may be more abbreviation

diff  --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugAbbrevTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugAbbrevTest.cpp
index ad61ccbc22c95..62627ae6956ff 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugAbbrevTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugAbbrevTest.cpp
@@ -42,6 +42,16 @@ void writeAbbreviationDeclarations(raw_ostream &OS, uint32_t FirstCode,
   encodeULEB128(0, OS);
 }
 
+void writeMalformedULEB128Value(raw_ostream &OS) {
+  OS << static_cast<uint8_t>(0x80);
+}
+
+void writeULEB128LargerThan64Bits(raw_ostream &OS) {
+  static constexpr llvm::StringRef LargeULEB128 =
+      "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01";
+  OS << LargeULEB128;
+}
+
 TEST(DWARFDebugAbbrevTest, DWARFAbbrevDeclSetExtractSuccess) {
   SmallString<64> RawData;
   raw_svector_ostream OS(RawData);
@@ -104,3 +114,168 @@ TEST(DWARFDebugAbbrevTest, DWARFAbbrevDeclSetExtractSuccessOutOfOrder) {
   EXPECT_FALSE(Abbrev1->hasChildren());
   EXPECT_EQ(Abbrev1->getNumAttributes(), 1u);
 }
+
+TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetCodeExtractionError) {
+  SmallString<64> RawData;
+
+  // Check for malformed ULEB128.
+  {
+    raw_svector_ostream OS(RawData);
+    writeMalformedULEB128Value(OS);
+
+    uint64_t Offset = 0;
+    DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
+    DWARFAbbreviationDeclarationSet AbbrevSet;
+    EXPECT_FALSE(AbbrevSet.extract(Data, &Offset));
+    EXPECT_EQ(Offset, 0u);
+  }
+
+  RawData.clear();
+  // Check for ULEB128 too large to fit into a uin64_t.
+  {
+    raw_svector_ostream OS(RawData);
+    writeULEB128LargerThan64Bits(OS);
+
+    uint64_t Offset = 0;
+    DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
+    DWARFAbbreviationDeclarationSet AbbrevSet;
+    EXPECT_FALSE(AbbrevSet.extract(Data, &Offset));
+    EXPECT_EQ(Offset, 0u);
+  }
+}
+
+TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetTagExtractionError) {
+  SmallString<64> RawData;
+  const uint32_t Code = 1;
+
+  // Check for malformed ULEB128.
+  {
+    raw_svector_ostream OS(RawData);
+    encodeULEB128(Code, OS);
+    writeMalformedULEB128Value(OS);
+
+    uint64_t Offset = 0;
+    DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
+    DWARFAbbreviationDeclarationSet AbbrevSet;
+    EXPECT_TRUE(AbbrevSet.extract(Data, &Offset));
+    // Only the code was extracted correctly.
+    EXPECT_EQ(Offset, 1u);
+  }
+
+  RawData.clear();
+  // Check for ULEB128 too large to fit into a uint64_t.
+  {
+    raw_svector_ostream OS(RawData);
+    encodeULEB128(Code, OS);
+    writeULEB128LargerThan64Bits(OS);
+
+    uint64_t Offset = 0;
+    DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
+    DWARFAbbreviationDeclarationSet AbbrevSet;
+    EXPECT_TRUE(AbbrevSet.extract(Data, &Offset));
+    // Only the code was extracted correctly.
+    EXPECT_EQ(Offset, 1u);
+  }
+}
+
+TEST(DWARFDebugAbbrevTest, DWARFAbbreviatioDeclSetChildExtractionError) {
+  SmallString<64> RawData;
+  const uint32_t Code = 1;
+  const dwarf::Tag Tag = DW_TAG_compile_unit;
+
+  // We want to make sure that we fail if we reach the end of the stream before
+  // reading the 'children' byte.
+  raw_svector_ostream OS(RawData);
+  encodeULEB128(Code, OS);
+  encodeULEB128(Tag, OS);
+
+  uint64_t Offset = 0;
+  DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
+  DWARFAbbreviationDeclarationSet AbbrevSet;
+  EXPECT_TRUE(AbbrevSet.extract(Data, &Offset));
+  // The code and the tag were extracted correctly.
+  EXPECT_EQ(Offset, 2u);
+}
+
+TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetAttributeExtractionError) {
+  SmallString<64> RawData;
+  const uint32_t Code = 1;
+  const dwarf::Tag Tag = DW_TAG_compile_unit;
+  const uint8_t Children = DW_CHILDREN_yes;
+
+  // Check for malformed ULEB128.
+  {
+    raw_svector_ostream OS(RawData);
+    encodeULEB128(Code, OS);
+    encodeULEB128(Tag, OS);
+    OS << Children;
+    writeMalformedULEB128Value(OS);
+
+    uint64_t Offset = 0;
+    DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
+    DWARFAbbreviationDeclarationSet AbbrevSet;
+    EXPECT_TRUE(AbbrevSet.extract(Data, &Offset));
+    // The code, tag, and child byte were extracted correctly.
+    EXPECT_EQ(Offset, 3u);
+  }
+
+  RawData.clear();
+  // Check for ULEB128 too large to fit into a uint64_t.
+  {
+    raw_svector_ostream OS(RawData);
+    encodeULEB128(Code, OS);
+    encodeULEB128(Tag, OS);
+    OS << Children;
+    writeULEB128LargerThan64Bits(OS);
+
+    uint64_t Offset = 0;
+    DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
+    DWARFAbbreviationDeclarationSet AbbrevSet;
+    EXPECT_TRUE(AbbrevSet.extract(Data, &Offset));
+    // The code, tag, and child byte were extracted correctly.
+    EXPECT_EQ(Offset, 3u);
+  }
+}
+
+TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetFormExtractionError) {
+  SmallString<64> RawData;
+  const uint32_t Code = 1;
+  const dwarf::Tag Tag = DW_TAG_compile_unit;
+  const uint8_t Children = DW_CHILDREN_yes;
+  const dwarf::Attribute Attr = DW_AT_name;
+
+  // Check for malformed ULEB128.
+  {
+    raw_svector_ostream OS(RawData);
+    encodeULEB128(Code, OS);
+    encodeULEB128(Tag, OS);
+    OS << Children;
+    encodeULEB128(Attr, OS);
+    writeMalformedULEB128Value(OS);
+
+    uint64_t Offset = 0;
+    DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
+    DWARFAbbreviationDeclarationSet AbbrevSet;
+    EXPECT_TRUE(AbbrevSet.extract(Data, &Offset));
+    // The code, tag, child byte, and first attribute were extracted correctly.
+    EXPECT_EQ(Offset, 4u);
+  }
+
+  RawData.clear();
+  // Check for ULEB128 too large to fit into a uint64_t.
+  {
+    raw_svector_ostream OS(RawData);
+    encodeULEB128(Code, OS);
+    encodeULEB128(Tag, OS);
+    OS << Children;
+    encodeULEB128(Attr, OS);
+    writeULEB128LargerThan64Bits(OS);
+
+    uint64_t Offset = 0;
+    DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));
+    DWARFAbbreviationDeclarationSet AbbrevSet;
+    EXPECT_TRUE(AbbrevSet.extract(Data, &Offset));
+    // The code, tag, child byte, and first attribute were extracted correctly.
+    EXPECT_EQ(Offset, 4u);
+  }
+}


        


More information about the llvm-commits mailing list