diff --git a/llvm/test/tools/llvm-objdump/ELF/invalid-verdef.test b/llvm/test/tools/llvm-objdump/ELF/invalid-verdef.test new file mode 100644 index 0000000000000..9f6ea6d1c5193 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/ELF/invalid-verdef.test @@ -0,0 +1,25 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-objdump -p %t 2>&1 | FileCheck --check-prefix=BROKEN-VERDEF -DFILE=%t %s + +## Ensure we emit a warning when vd_aux offset field is invalid. + +# BROKEN-VERDEF: Version definitions: +# BROKEN-VERDEF-NEXT: warning: '[[FILE]]': corrupted section: vd_aux value 69 in section verdef points past end of the section + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN +Sections: + - Name: .gnu.version_d + Type: SHT_GNU_verdef + Entries: + - Version: 1 + Flags: 0 + VersionNdx: 0 + VDAux: 69 + Names: + - VERSION_1 +DynamicSymbols: [] +... diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp index 5ac13495662fa..bfa5f57d2f0ec 100644 --- a/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/llvm/tools/llvm-objdump/ELFDump.cpp @@ -39,6 +39,9 @@ template class ELFDumper : public Dumper { void printProgramHeaders(); void printSymbolVersion(); void printSymbolVersionDependency(const typename ELFT::Shdr &Sec); + void printSymbolVersionDefinition(const typename ELFT::Shdr &Shdr, + ArrayRef Contents, + StringRef StrTab); }; } // namespace @@ -380,9 +383,9 @@ void ELFDumper::printSymbolVersionDependency( } template -static void printSymbolVersionDefinition(const typename ELFT::Shdr &Shdr, - ArrayRef Contents, - StringRef StrTab) { +void ELFDumper::printSymbolVersionDefinition( + const typename ELFT::Shdr &Shdr, ArrayRef Contents, + StringRef StrTab) { outs() << "\nVersion definitions:\n"; const uint8_t *Buf = Contents.data(); @@ -398,6 +401,12 @@ static void printSymbolVersionDefinition(const typename ELFT::Shdr &Shdr, << format("0x%08" PRIx32 " ", (uint32_t)Verdef->vd_hash); const uint8_t *BufAux = Buf + Verdef->vd_aux; + if (BufAux > Contents.end()) { + reportWarning("corrupted section: vd_aux value " + Twine(Verdef->vd_aux) + + " in section verdef points past end of the section", + Obj.getFileName()); + break; + } uint16_t VerdauxIndex = 0; while (BufAux) { auto *Verdaux = reinterpret_cast(BufAux); @@ -430,7 +439,7 @@ template void ELFDumper::printSymbolVersion() { if (Shdr.sh_type == ELF::SHT_GNU_verneed) printSymbolVersionDependency(Shdr); else - printSymbolVersionDefinition(Shdr, Contents, StrTab); + printSymbolVersionDefinition(Shdr, Contents, StrTab); } }