aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-objdump
diff options
context:
space:
mode:
authorRuoyu Qiu <cabbaken@outlook.com>2025-03-10 10:39:58 +0800
committerGitHub <noreply@github.com>2025-03-09 19:39:58 -0700
commit82f2b661101d1133b72872141009035f01a42595 (patch)
treefa2b9f64f8687fd13d5c0b3f6792cf312ac8a896 /llvm/tools/llvm-objdump
parent42d49a77241df73a17cb442973702fc460e7fb90 (diff)
downloadllvm-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.cpp21
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;