diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp @@ -38,18 +38,28 @@ 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 Err; + if (Code == 0) return ExtractState::Complete; CodeByteSize = *OffsetPtr - Offset; - Tag = static_cast(Data.getULEB128(OffsetPtr)); + Tag = static_cast(Data.getULEB128(OffsetPtr, &Err)); + if (Err) + return Err; + if (Tag == DW_TAG_null) { clear(); return make_error( "abbreviation declaration requires a non-null tag"); } - uint8_t ChildrenByte = Data.getU8(OffsetPtr); + uint8_t ChildrenByte = Data.getU8(OffsetPtr, &Err); + if (Err) + return 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 @@ // Read all of the abbreviation attributes and forms. while (Data.isValidOffset(*OffsetPtr)) { - auto A = static_cast(Data.getULEB128(OffsetPtr)); - auto F = static_cast
(Data.getULEB128(OffsetPtr)); + auto A = static_cast(Data.getULEB128(OffsetPtr, &Err)); + if (Err) + return Err; + + auto F = static_cast(Data.getULEB128(OffsetPtr, &Err)); + if (Err) + return 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 --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugAbbrevTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugAbbrevTest.cpp @@ -42,6 +42,12 @@ encodeULEB128(0, OS); } +void writeBadAbbreviationDeclarationData(raw_ostream &OS, size_t Size, + uint32_t Data) { + std::vector BadData((Size / 4) + 1, Data); + OS.write(reinterpret_cast(BadData.data()), Size); +} + TEST(DWARFDebugAbbrevTest, DWARFAbbrevDeclSetExtractSuccess) { SmallString<64> RawData; raw_svector_ostream OS(RawData); @@ -104,3 +110,18 @@ EXPECT_FALSE(Abbrev1->hasChildren()); EXPECT_EQ(Abbrev1->getNumAttributes(), 1u); } + +TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetBadData) { + SmallString<64> RawData; + raw_svector_ostream OS(RawData); + const uint32_t DataSize = 72; // This number is arbitrary. + const uint32_t DataContents = 0xDEADBEEFu; + + writeBadAbbreviationDeclarationData(OS, DataSize, DataContents); + + uint64_t Offset = 0; + DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t)); + DWARFAbbreviationDeclarationSet AbbrevSet; + const bool DataWasExtracted = AbbrevSet.extract(Data, &Offset); + EXPECT_FALSE(DataWasExtracted); +}