diff options
author | Ruoyu Qiu <cabbaken@outlook.com> | 2025-03-10 10:39:58 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-03-09 19:39:58 -0700 |
commit | 82f2b661101d1133b72872141009035f01a42595 (patch) | |
tree | fa2b9f64f8687fd13d5c0b3f6792cf312ac8a896 /llvm/tools/llvm-objdump | |
parent | 42d49a77241df73a17cb442973702fc460e7fb90 (diff) | |
download | llvm-82f2b661101d1133b72872141009035f01a42595.zip llvm-82f2b661101d1133b72872141009035f01a42595.tar.gz llvm-82f2b661101d1133b72872141009035f01a42595.tar.bz2 |
[llvm-objdump][ELF]Fix crash when reading strings from .dynstr (#125679)
This change introduces a check for the strtab offset to prevent
llvm-objdump from crashing when processing malformed ELF files.
It provide a minimal reproduce test for
https://github.com/llvm/llvm-project/issues/86612#issuecomment-2035694455.
Additionally, it modifies how llvm-objdump handles and outputs malformed
ELF files with invalid string offsets.(More info:
https://discourse.llvm.org/t/should-llvm-objdump-objdump-display-actual-corrupted-values-in-malformed-elf-files/84391)
Fixes: #86612
Co-authored-by: James Henderson <James.Henderson@sony.com>
Diffstat (limited to 'llvm/tools/llvm-objdump')
-rw-r--r-- | llvm/tools/llvm-objdump/ELFDump.cpp | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp index b7899bc..3b288ea 100644 --- a/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/llvm/tools/llvm-objdump/ELFDump.cpp @@ -63,16 +63,24 @@ static Expected<StringRef> getDynamicStrTab(const ELFFile<ELFT> &Elf) { if (!DynamicEntriesOrError) return DynamicEntriesOrError.takeError(); + typename ELFT::Xword StringTableSize{0}; + const uint8_t *MappedAddr = nullptr; for (const typename ELFT::Dyn &Dyn : *DynamicEntriesOrError) { if (Dyn.d_tag == ELF::DT_STRTAB) { auto MappedAddrOrError = Elf.toMappedAddr(Dyn.getPtr()); if (!MappedAddrOrError) return MappedAddrOrError.takeError(); - return StringRef(reinterpret_cast<const char *>(*MappedAddrOrError)); + MappedAddr = *MappedAddrOrError; } + if (Dyn.d_tag == ELF::DT_STRSZ) + StringTableSize = Dyn.getVal(); } + if (MappedAddr && StringTableSize) + return StringRef(reinterpret_cast<const char *>(MappedAddr), + StringTableSize); - // If the dynamic segment is not present, we fall back on the sections. + // If the dynamic segment is not present, or is missing the important tags, we + // fall back on the sections. auto SectionsOrError = Elf.sections(); if (!SectionsOrError) return SectionsOrError.takeError(); @@ -221,6 +229,7 @@ template <class ELFT> void ELFDumper<ELFT>::printDynamicSection() { std::string TagFmt = " %-" + std::to_string(MaxLen) + "s "; outs() << "\nDynamic Section:\n"; + for (const typename ELFT::Dyn &Dyn : DynamicEntries) { if (Dyn.d_tag == ELF::DT_NULL) continue; @@ -235,6 +244,14 @@ template <class ELFT> void ELFDumper<ELFT>::printDynamicSection() { Expected<StringRef> StrTabOrErr = getDynamicStrTab(Elf); if (StrTabOrErr) { const char *Data = StrTabOrErr->data(); + if (Dyn.getVal() >= StrTabOrErr->size()) { + reportWarning("invalid string table offset, string table size: 0x" + + Twine::utohexstr(StrTabOrErr->size()), + Obj.getFileName()); + outs() << format(TagFmt.c_str(), Str.c_str()) + << format(Fmt, (uint64_t)Dyn.getVal()); + continue; + } outs() << format(TagFmt.c_str(), Str.c_str()) << Data + Dyn.getVal() << "\n"; continue; |