diff options
| -rw-r--r-- | llvm/include/llvm/Object/ELF.h | 76 | ||||
| -rw-r--r-- | llvm/include/llvm/Object/Error.h | 1 | ||||
| -rw-r--r-- | llvm/lib/Object/Error.cpp | 2 | ||||
| -rw-r--r-- | llvm/test/Object/Inputs/invalid-strtab-size.elf | bin | 0 -> 536 bytes | |||
| -rw-r--r-- | llvm/test/Object/invalid.test | 1 | ||||
| -rw-r--r-- | llvm/tools/llvm-objdump/llvm-objdump.cpp | 6 | ||||
| -rw-r--r-- | llvm/tools/llvm-readobj/ELFDumper.cpp | 7 | ||||
| -rw-r--r-- | llvm/tools/obj2yaml/elf2yaml.cpp | 12 |
8 files changed, 67 insertions, 38 deletions
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h index 662057a40b5..54ab3f922b8 100644 --- a/llvm/include/llvm/Object/ELF.h +++ b/llvm/include/llvm/Object/ELF.h @@ -172,8 +172,8 @@ private: const Elf_Ehdr *Header; const Elf_Shdr *SectionHeaderTable; - const Elf_Shdr *dot_shstrtab_sec; // Section header string table. - const Elf_Shdr *dot_strtab_sec; // Symbol header string table. + StringRef DotShstrtab; // Section header string table. + StringRef DotStrtab; // Symbol header string table. const Elf_Shdr *dot_symtab_sec; // Symbol table section. const Elf_Shdr *SymbolTableSectionHeaderIndex; @@ -235,7 +235,7 @@ public: const T *getEntry(uint32_t Section, uint32_t Entry) const; template <typename T> const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; - ErrorOr<StringRef> getString(const Elf_Shdr *Section, uint32_t Offset) const; + ErrorOr<StringRef> getStringTable(const Elf_Shdr *Section) const; const char *getDynamicString(uintX_t Offset) const; ErrorOr<StringRef> getSymbolVersion(const Elf_Shdr *section, const Elf_Sym *Symb, @@ -371,8 +371,7 @@ public: /// /// \p SymTab is used to lookup the string table to use to get the symbol's /// name. - ErrorOr<StringRef> getSymbolName(const Elf_Shdr *StrTab, - const Elf_Sym *Symb) const; + ErrorOr<StringRef> getSymbolName(StringRef StrTab, const Elf_Sym *Symb) const; ErrorOr<StringRef> getSectionName(const Elf_Shdr *Section) const; uint64_t getSymbolIndex(const Elf_Sym *sym) const; ErrorOr<ArrayRef<uint8_t> > getSectionContents(const Elf_Shdr *Sec) const; @@ -545,15 +544,6 @@ ELFFile<ELFT>::getRelocationSymbol(const Elf_Shdr *Sec, const RelT *Rel) const { SymTable, getEntry<Elf_Sym>(SymTable, Rel->getSymbol(isMips64EL()))); } -// Verify that the last byte in the string table in a null. -template <class ELFT> -void ELFFile<ELFT>::VerifyStrTab(const Elf_Shdr *sh) const { - const char *strtab = (const char *)base() + sh->sh_offset; - if (strtab[sh->sh_size - 1] != 0) - // FIXME: Proper error handling. - report_fatal_error("String table must end with a null terminator!"); -} - template <class ELFT> uint64_t ELFFile<ELFT>::getNumSections() const { assert(Header && "Header not initialized!"); @@ -577,8 +567,7 @@ typename ELFFile<ELFT>::uintX_t ELFFile<ELFT>::getStringTableIndex() const { template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC) - : Buf(Object), SectionHeaderTable(nullptr), dot_shstrtab_sec(nullptr), - dot_strtab_sec(nullptr), dot_symtab_sec(nullptr), + : Buf(Object), SectionHeaderTable(nullptr), dot_symtab_sec(nullptr), SymbolTableSectionHeaderIndex(nullptr), dot_gnu_version_sec(nullptr), dot_gnu_version_r_sec(nullptr), dot_gnu_version_d_sec(nullptr), dt_soname(nullptr) { @@ -626,15 +615,18 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC) } SymbolTableSectionHeaderIndex = &Sec; break; - case ELF::SHT_SYMTAB: + case ELF::SHT_SYMTAB: { if (dot_symtab_sec) { // More than one .symtab! EC = object_error::parse_failed; return; } dot_symtab_sec = &Sec; - dot_strtab_sec = getSection(Sec.sh_link); - break; + ErrorOr<StringRef> SymtabOrErr = getStringTable(getSection(Sec.sh_link)); + if ((EC = SymtabOrErr.getError())) + return; + DotStrtab = *SymtabOrErr; + } break; case ELF::SHT_DYNSYM: { if (DynSymRegion.Addr) { // More than one .dynsym! @@ -688,11 +680,11 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC) } // Get string table sections. - dot_shstrtab_sec = getSection(getStringTableIndex()); - if (dot_shstrtab_sec) { - // Verify that the last byte in the string table in a null. - VerifyStrTab(dot_shstrtab_sec); - } + ErrorOr<StringRef> SymtabOrErr = + getStringTable(getSection(getStringTableIndex())); + if ((EC = SymtabOrErr.getError())) + return; + DotShstrtab = *SymtabOrErr; // Build symbol name side-mapping if there is one. if (SymbolTableSectionHeaderIndex) { @@ -865,13 +857,18 @@ ELFFile<ELFT>::getSection(uint32_t index) const { } template <class ELFT> -ErrorOr<StringRef> ELFFile<ELFT>::getString(const Elf_Shdr *Section, - ELF::Elf32_Word Offset) const { +ErrorOr<StringRef> +ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section) const { if (Section->sh_type != ELF::SHT_STRTAB) return object_error::parse_failed; - if (Offset >= Section->sh_size) + uint64_t Offset = Section->sh_offset; + uint64_t Size = Section->sh_size; + if (Offset + Size > Buf.size()) return object_error::parse_failed; - return StringRef((const char *)base() + Section->sh_offset + Offset); + StringRef Data((const char *)base() + Section->sh_offset, Size); + if (Data[Size - 1] != '\0') + return object_error::string_table_non_null_end; + return Data; } template <class ELFT> @@ -884,7 +881,7 @@ const char *ELFFile<ELFT>::getDynamicString(uintX_t Offset) const { template <class ELFT> ErrorOr<StringRef> ELFFile<ELFT>::getStaticSymbolName(const Elf_Sym *Symb) const { - return getSymbolName(dot_strtab_sec, Symb); + return getSymbolName(DotStrtab, Symb); } template <class ELFT> @@ -902,27 +899,40 @@ ErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(const Elf_Sym *Symb, } template <class ELFT> -ErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(const Elf_Shdr *StrTab, +ErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(StringRef StrTab, const Elf_Sym *Sym) const { - return getString(StrTab, Sym->st_name); + uint32_t Offset = Sym->st_name; + if (Offset >= StrTab.size()) + return object_error::parse_failed; + return StringRef(StrTab.data() + Offset); } template <class ELFT> ErrorOr<StringRef> ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section) const { - return getString(dot_shstrtab_sec, Section->sh_name); + uint32_t Offset = Section->sh_name; + if (Offset >= DotShstrtab.size()) + return object_error::parse_failed; + return StringRef(DotShstrtab.data() + Offset); } template <class ELFT> ErrorOr<StringRef> ELFFile<ELFT>::getSymbolVersion(const Elf_Shdr *section, const Elf_Sym *symb, bool &IsDefault) const { + StringRef StrTab; + if (section) { + ErrorOr<StringRef> StrTabOrErr = getStringTable(section); + if (std::error_code EC = StrTabOrErr.getError()) + return EC; + StrTab = *StrTabOrErr; + } // Handle non-dynamic symbols. if (section != DynSymRegion.Addr && section != nullptr) { // Non-dynamic symbols can have versions in their names // A name of the form 'foo@V1' indicates version 'V1', non-default. // A name of the form 'foo@@V2' indicates version 'V2', default version. - ErrorOr<StringRef> SymName = getSymbolName(section, symb); + ErrorOr<StringRef> SymName = getSymbolName(StrTab, symb); if (!SymName) return SymName; StringRef Name = *SymName; diff --git a/llvm/include/llvm/Object/Error.h b/llvm/include/llvm/Object/Error.h index c9db1b80b91..1b0b56787c5 100644 --- a/llvm/include/llvm/Object/Error.h +++ b/llvm/include/llvm/Object/Error.h @@ -27,6 +27,7 @@ enum class object_error { invalid_file_type, parse_failed, unexpected_eof, + string_table_non_null_end, bitcode_section_not_found, macho_small_load_command, macho_load_segment_too_many_sections, diff --git a/llvm/lib/Object/Error.cpp b/llvm/lib/Object/Error.cpp index 644a178c162..5d613d77609 100644 --- a/llvm/lib/Object/Error.cpp +++ b/llvm/lib/Object/Error.cpp @@ -41,6 +41,8 @@ std::string _object_error_category::message(int EV) const { return "Invalid data was encountered while parsing the file"; case object_error::unexpected_eof: return "The end of the file was unexpectedly encountered"; + case object_error::string_table_non_null_end: + return "String table must end with a null terminator"; case object_error::bitcode_section_not_found: return "Bitcode section not found in object file"; case object_error::macho_small_load_command: diff --git a/llvm/test/Object/Inputs/invalid-strtab-size.elf b/llvm/test/Object/Inputs/invalid-strtab-size.elf Binary files differnew file mode 100644 index 00000000000..fb1974613ab --- /dev/null +++ b/llvm/test/Object/Inputs/invalid-strtab-size.elf diff --git a/llvm/test/Object/invalid.test b/llvm/test/Object/invalid.test index 17cbb30c9c2..73a6ad8021a 100644 --- a/llvm/test/Object/invalid.test +++ b/llvm/test/Object/invalid.test @@ -1,5 +1,6 @@ RUN: not llvm-dwarfdump %p/Inputs/invalid-bad-rel-type.elf 2>&1 | FileCheck %s RUN: not llvm-objdump -s %p/Inputs/invalid-strtab-type.elf 2>&1 | FileCheck %s +RUN: not llvm-objdump -s %p/Inputs/invalid-strtab-size.elf 2>&1 | FileCheck %s CHECK: Invalid data was encountered while parsing the file RUN: not llvm-objdump -s %p/Inputs/invalid-strtab-non-null.elf 2>&1 | FileCheck --check-prefix=NON-NULL %s diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 610d54877ea..33308234e7d 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -324,7 +324,11 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj, const Elf_Shdr *SymTab = EF.getSection(sec->sh_link); assert(SymTab->sh_type == ELF::SHT_SYMTAB || SymTab->sh_type == ELF::SHT_DYNSYM); - const Elf_Shdr *StrTab = EF.getSection(SymTab->sh_link); + const Elf_Shdr *StrTabSec = EF.getSection(SymTab->sh_link); + ErrorOr<StringRef> StrTabOrErr = EF.getStringTable(StrTabSec); + if (std::error_code EC = StrTabOrErr.getError()) + return EC; + StringRef StrTab = *StrTabOrErr; uint8_t type; StringRef res; int64_t addend = 0; diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 76b71c517fd..b1ba0906f69 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -757,8 +757,11 @@ void ELFDumper<ELFT>::printRelocation(const Elf_Shdr *Sec, TargetName = SecName.get(); } else if (Sym.first) { const Elf_Shdr *SymTable = Sym.first; - const Elf_Shdr *StrTable = Obj->getSection(SymTable->sh_link); - TargetName = errorOrDefault(Obj->getSymbolName(StrTable, Sym.second)); + const Elf_Shdr *StrTableSec = Obj->getSection(SymTable->sh_link); + ErrorOr<StringRef> StrTableOrErr = Obj->getStringTable(StrTableSec); + if (!error(StrTableOrErr.getError())) + TargetName = + errorOrDefault(Obj->getSymbolName(*StrTableOrErr, Sym.second)); } if (opts::ExpandRelocs) { diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp index db29d2db390..73c83d897d9 100644 --- a/llvm/tools/obj2yaml/elf2yaml.cpp +++ b/llvm/tools/obj2yaml/elf2yaml.cpp @@ -183,7 +183,11 @@ std::error_code ELFDumper<ELFT>::dumpRelocation(const Elf_Shdr *Shdr, return obj2yaml_error::success; const Elf_Shdr *SymTab = NamePair.first; - const Elf_Shdr *StrTab = Obj.getSection(SymTab->sh_link); + const Elf_Shdr *StrTabSec = Obj.getSection(SymTab->sh_link); + ErrorOr<StringRef> StrTabOrErr = Obj.getStringTable(StrTabSec); + if (std::error_code EC = StrTabOrErr.getError()) + return EC; + StringRef StrTab = *StrTabOrErr; ErrorOr<StringRef> NameOrErr = Obj.getSymbolName(StrTab, NamePair.second); if (std::error_code EC = NameOrErr.getError()) @@ -302,7 +306,11 @@ ErrorOr<ELFYAML::Group *> ELFDumper<ELFT>::dumpGroup(const Elf_Shdr *Shdr) { // Get sh_info which is the signature. const Elf_Sym *symbol = Obj.getSymbol(Shdr->sh_info); const Elf_Shdr *symtab = Obj.getSection(Shdr->sh_link); - const Elf_Shdr *StrTab = Obj.getSection(symtab->sh_link); + const Elf_Shdr *StrTabSec = Obj.getSection(symtab->sh_link); + ErrorOr<StringRef> StrTabOrErr = Obj.getStringTable(StrTabSec); + if (std::error_code EC = StrTabOrErr.getError()) + return EC; + StringRef StrTab = *StrTabOrErr; auto sectionContents = Obj.getSectionContents(Shdr); if (std::error_code ec = sectionContents.getError()) return ec; |

