[llvm] [libDebugInfo] Prevent infinite recursion in DWARFDie::getTypeSize() (PR #74681)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 6 16:35:19 PST 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-debuginfo
Author: Adrian Prantl (adrian-prantl)
<details>
<summary>Changes</summary>
when run on invalid input.
---
Full diff: https://github.com/llvm/llvm-project/pull/74681.diff
5 Files Affected:
- (modified) llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h (+4-1)
- (modified) llvm/lib/DebugInfo/DWARF/DWARFContext.cpp (+4-2)
- (modified) llvm/lib/DebugInfo/DWARF/DWARFDie.cpp (+10-4)
- (modified) llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp (+5-2)
- (modified) llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp (+39)
``````````diff
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h
index 421b84d644db64..5ccd93a979fe1b 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h
@@ -10,6 +10,7 @@
#define LLVM_DEBUGINFO_DWARF_DWARFDIE_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/BinaryFormat/Dwarf.h"
@@ -284,7 +285,9 @@ class DWARFDie {
/// \param PointerSize the pointer size of the containing CU.
/// \returns if this is a type DIE, or this DIE contains a DW_AT_type, returns
/// the size of the type.
- std::optional<uint64_t> getTypeSize(uint64_t PointerSize);
+ std::optional<uint64_t>
+ getTypeSize(uint64_t PointerSize,
+ llvm::SmallPtrSetImpl<const DWARFDebugInfoEntry *> &visited);
class iterator;
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index c671aedbc9e52b..87af76ae72ae0e 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -1663,8 +1663,10 @@ void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram,
if (auto NameAttr = Die.find(DW_AT_name))
if (std::optional<const char *> Name = dwarf::toString(*NameAttr))
Local.Name = *Name;
- if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type))
- Local.Size = Type.getTypeSize(getCUAddrSize());
+ if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type)) {
+ llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> visited;
+ Local.Size = Type.getTypeSize(getCUAddrSize(), visited);
+ }
if (auto DeclFileAttr = Die.find(DW_AT_decl_file)) {
if (const auto *LT = CU->getContext().getLineTableForUnit(CU))
LT->getFileNameByIndex(
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index 0f01933002c06d..3fec05e49a9210 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -489,7 +489,12 @@ void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0);
}
-std::optional<uint64_t> DWARFDie::getTypeSize(uint64_t PointerSize) {
+std::optional<uint64_t>
+DWARFDie::getTypeSize(uint64_t PointerSize,
+ SmallPtrSetImpl<const DWARFDebugInfoEntry *> &visited) {
+ // Cycle detected?
+ if (!visited.insert(Die).second)
+ return {};
if (auto SizeAttr = find(DW_AT_byte_size))
if (std::optional<uint64_t> Size = SizeAttr->getAsUnsignedConstant())
return Size;
@@ -511,14 +516,15 @@ std::optional<uint64_t> DWARFDie::getTypeSize(uint64_t PointerSize) {
case DW_TAG_restrict_type:
case DW_TAG_typedef: {
if (DWARFDie BaseType = getAttributeValueAsReferencedDie(DW_AT_type))
- return BaseType.getTypeSize(PointerSize);
+ return BaseType.getTypeSize(PointerSize, visited);
break;
}
case DW_TAG_array_type: {
DWARFDie BaseType = getAttributeValueAsReferencedDie(DW_AT_type);
if (!BaseType)
return std::nullopt;
- std::optional<uint64_t> BaseSize = BaseType.getTypeSize(PointerSize);
+ std::optional<uint64_t> BaseSize =
+ BaseType.getTypeSize(PointerSize, visited);
if (!BaseSize)
return std::nullopt;
uint64_t Size = *BaseSize;
@@ -543,7 +549,7 @@ std::optional<uint64_t> DWARFDie::getTypeSize(uint64_t PointerSize) {
}
default:
if (DWARFDie BaseType = getAttributeValueAsReferencedDie(DW_AT_type))
- return BaseType.getTypeSize(PointerSize);
+ return BaseType.getTypeSize(PointerSize, visited);
break;
}
return std::nullopt;
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index 9f455fa7e96a7e..8ac31e4a2a94fa 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -817,9 +817,12 @@ void DWARFUnit::updateVariableDieMap(DWARFDie Die) {
// no type), then we use a size of one to still allow symbolization of the
// exact address.
uint64_t GVSize = 1;
- if (Die.getAttributeValueAsReferencedDie(DW_AT_type))
- if (std::optional<uint64_t> Size = Die.getTypeSize(getAddressByteSize()))
+ if (Die.getAttributeValueAsReferencedDie(DW_AT_type)) {
+ llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> visited;
+ if (std::optional<uint64_t> Size =
+ Die.getTypeSize(getAddressByteSize(), visited))
GVSize = *Size;
+ }
if (Address != UINT64_MAX)
VariableDieMap[Address] = {Address + GVSize, Die};
diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
index 0b7f8f41bc53f4..7b9b25eaf5b750 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
@@ -1615,6 +1615,45 @@ TEST(DWARFDebugInfo, TestFindRecurse) {
EXPECT_EQ(AbsDieName, StringOpt.value_or(nullptr));
}
+TEST(DWARFDebugInfo, TestSelfRecursiveType) {
+ typedef uint32_t AddrType;
+ Triple Triple = getDefaultTargetTripleForAddrSize(sizeof(AddrType));
+ if (!isConfigurationSupported(Triple))
+ GTEST_SKIP();
+
+ auto ExpectedDG = dwarfgen::Generator::create(Triple, 4);
+ ASSERT_THAT_EXPECTED(ExpectedDG, Succeeded());
+ dwarfgen::Generator *DG = ExpectedDG.get().get();
+ dwarfgen::CompileUnit &CU = DG->addCompileUnit();
+ dwarfgen::DIE CUDie = CU.getUnitDIE();
+
+ // Create an invalid self-recursive typedef.
+ dwarfgen::DIE TypedefDie = CUDie.addChild(DW_TAG_typedef);
+ TypedefDie.addAttribute(DW_AT_name, DW_FORM_strp, "illegal");
+ TypedefDie.addAttribute(DW_AT_type, DW_FORM_ref_addr, TypedefDie);
+
+ MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
+ auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
+ EXPECT_TRUE((bool)Obj);
+ std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
+
+ // Verify the number of compile units is correct.
+ uint32_t NumCUs = DwarfContext->getNumCompileUnits();
+ EXPECT_EQ(NumCUs, 1u);
+ DWARFCompileUnit *U =
+ cast<DWARFCompileUnit>(DwarfContext->getUnitAtIndex(0));
+
+ {
+ DWARFDie CUDie = U->getUnitDIE(false);
+ EXPECT_TRUE(CUDie.isValid());
+ DWARFDie TypedefDie = CUDie.getFirstChild();
+
+ // Test that getTypeSize doesn't get into an infinite loop.
+ llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 1> visited;
+ EXPECT_EQ(TypedefDie.getTypeSize(sizeof(AddrType), visited), std::nullopt);
+ }
+}
+
TEST(DWARFDebugInfo, TestDwarfToFunctions) {
// Test all of the dwarf::toXXX functions that take a
// std::optional<DWARFFormValue> and extract the values from it.
``````````
</details>
https://github.com/llvm/llvm-project/pull/74681
More information about the llvm-commits
mailing list