[lldb/DWARF] Fix a crash parsing invalid dwarf (pr49678)
If the debug info is missing the terminating null die, we would crash
when trying to access the nonexisting children/siblings. This was
discovered because the test case for D98619 accidentaly produced such
input.
GitOrigin-RevId: 2ecf928153fc56dcb6bb0bd910584eac86bc23bd
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 86b1861..ea10ba7 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -236,6 +236,11 @@
}
if (!m_die_array.empty()) {
+ // The last die cannot have children (if it did, it wouldn't be the last one).
+ // This only makes a difference for malformed dwarf that does not have a
+ // terminating null die.
+ m_die_array.back().SetHasChildren(false);
+
if (m_first_die) {
// Only needed for the assertion.
m_first_die.SetHasChildren(m_die_array.front().HasChildren());
diff --git a/unittests/SymbolFile/DWARF/DWARFUnitTest.cpp b/unittests/SymbolFile/DWARF/DWARFUnitTest.cpp
index 3a4b1cf..f5cfd1e 100644
--- a/unittests/SymbolFile/DWARF/DWARFUnitTest.cpp
+++ b/unittests/SymbolFile/DWARF/DWARFUnitTest.cpp
@@ -47,3 +47,40 @@
ASSERT_NE(die_first, nullptr);
EXPECT_TRUE(die_first->IsNULL());
}
+
+TEST(DWARFUnitTest, MissingSentinel) {
+ // Make sure we don't crash if the debug info is missing a null DIE sentinel.
+ const char *yamldata = R"(
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_386
+DWARF:
+ debug_abbrev:
+ - Table:
+ - Code: 0x00000001
+ Tag: DW_TAG_compile_unit
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_language
+ Form: DW_FORM_data2
+ debug_info:
+ - Version: 4
+ AddrSize: 8
+ Entries:
+ - AbbrCode: 0x00000001
+ Values:
+ - Value: 0x000000000000000C
+)";
+
+ YAMLModuleTester t(yamldata);
+ ASSERT_TRUE((bool)t.GetDwarfUnit());
+
+ DWARFUnit *unit = t.GetDwarfUnit();
+ const DWARFDebugInfoEntry *die_first = unit->DIE().GetDIE();
+ ASSERT_NE(die_first, nullptr);
+ EXPECT_EQ(die_first->GetFirstChild(), nullptr);
+ EXPECT_EQ(die_first->GetSibling(), nullptr);
+}