From 9a6c9023325b44115e5559098c4e01914d13ee82 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Mon, 29 Jun 2015 14:39:25 +0000 Subject: [PATCH] Factor out the checking of string tables. This moves the error checking for string tables to getStringTable which returns an ErrorOr. This improves error checking, makes it uniform across all string tables and makes it possible to check them once instead of once per name. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@240950 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/ELF.h | 76 ++++++++++++--------- include/llvm/Object/Error.h | 1 + lib/Object/Error.cpp | 2 + test/Object/Inputs/invalid-strtab-size.elf | Bin 0 -> 536 bytes test/Object/invalid.test | 1 + tools/llvm-objdump/llvm-objdump.cpp | 6 +- tools/llvm-readobj/ELFDumper.cpp | 7 +- tools/obj2yaml/elf2yaml.cpp | 12 +++- 8 files changed, 67 insertions(+), 38 deletions(-) create mode 100644 test/Object/Inputs/invalid-strtab-size.elf diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 662057a40b5..54ab3f922b8 100644 --- a/include/llvm/Object/ELF.h +++ b/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 const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; - ErrorOr getString(const Elf_Shdr *Section, uint32_t Offset) const; + ErrorOr getStringTable(const Elf_Shdr *Section) const; const char *getDynamicString(uintX_t Offset) const; ErrorOr 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 getSymbolName(const Elf_Shdr *StrTab, - const Elf_Sym *Symb) const; + ErrorOr getSymbolName(StringRef StrTab, const Elf_Sym *Symb) const; ErrorOr getSectionName(const Elf_Shdr *Section) const; uint64_t getSymbolIndex(const Elf_Sym *sym) const; ErrorOr > getSectionContents(const Elf_Shdr *Sec) const; @@ -545,15 +544,6 @@ ELFFile::getRelocationSymbol(const Elf_Shdr *Sec, const RelT *Rel) const { SymTable, getEntry(SymTable, Rel->getSymbol(isMips64EL()))); } -// Verify that the last byte in the string table in a null. -template -void ELFFile::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 uint64_t ELFFile::getNumSections() const { assert(Header && "Header not initialized!"); @@ -577,8 +567,7 @@ typename ELFFile::uintX_t ELFFile::getStringTableIndex() const { template ELFFile::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::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 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::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 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::getSection(uint32_t index) const { } template -ErrorOr ELFFile::getString(const Elf_Shdr *Section, - ELF::Elf32_Word Offset) const { +ErrorOr +ELFFile::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 @@ -884,7 +881,7 @@ const char *ELFFile::getDynamicString(uintX_t Offset) const { template ErrorOr ELFFile::getStaticSymbolName(const Elf_Sym *Symb) const { - return getSymbolName(dot_strtab_sec, Symb); + return getSymbolName(DotStrtab, Symb); } template @@ -902,27 +899,40 @@ ErrorOr ELFFile::getSymbolName(const Elf_Sym *Symb, } template -ErrorOr ELFFile::getSymbolName(const Elf_Shdr *StrTab, +ErrorOr ELFFile::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 ErrorOr ELFFile::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 ErrorOr ELFFile::getSymbolVersion(const Elf_Shdr *section, const Elf_Sym *symb, bool &IsDefault) const { + StringRef StrTab; + if (section) { + ErrorOr 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 SymName = getSymbolName(section, symb); + ErrorOr SymName = getSymbolName(StrTab, symb); if (!SymName) return SymName; StringRef Name = *SymName; diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h index c9db1b80b91..1b0b56787c5 100644 --- a/include/llvm/Object/Error.h +++ b/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/lib/Object/Error.cpp b/lib/Object/Error.cpp index 644a178c162..5d613d77609 100644 --- a/lib/Object/Error.cpp +++ b/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/test/Object/Inputs/invalid-strtab-size.elf b/test/Object/Inputs/invalid-strtab-size.elf new file mode 100644 index 0000000000000000000000000000000000000000..fb1974613ab297d7716ad02940f5342574efad0c GIT binary patch literal 536 zcmb<-^>JfjWMpQ50!9Wq21XbMiJpPPb^x;-7}&6?geX)1Q%n#JGO1URT2aEFmsDKL zpjTW{RFaqkq$_j5bV_1LBC=Wv*gQbJa8DtbQvhZE|NkFJlmWvhpfCVoHWXD13=U{~ z7?%acfYLHR8l)fH4GvIwbP8QRJ5T`!5RJ_0CfP!jUaU(yFfq!LNNdU DY}yjI literal 0 HcmV?d00001 diff --git a/test/Object/invalid.test b/test/Object/invalid.test index 17cbb30c9c2..73a6ad8021a 100644 --- a/test/Object/invalid.test +++ b/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/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 610d54877ea..33308234e7d 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -324,7 +324,11 @@ static std::error_code getRelocationValueString(const ELFObjectFile *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 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/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index 76b71c517fd..b1ba0906f69 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -757,8 +757,11 @@ void ELFDumper::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 StrTableOrErr = Obj->getStringTable(StrTableSec); + if (!error(StrTableOrErr.getError())) + TargetName = + errorOrDefault(Obj->getSymbolName(*StrTableOrErr, Sym.second)); } if (opts::ExpandRelocs) { diff --git a/tools/obj2yaml/elf2yaml.cpp b/tools/obj2yaml/elf2yaml.cpp index db29d2db390..73c83d897d9 100644 --- a/tools/obj2yaml/elf2yaml.cpp +++ b/tools/obj2yaml/elf2yaml.cpp @@ -183,7 +183,11 @@ std::error_code ELFDumper::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 StrTabOrErr = Obj.getStringTable(StrTabSec); + if (std::error_code EC = StrTabOrErr.getError()) + return EC; + StringRef StrTab = *StrTabOrErr; ErrorOr NameOrErr = Obj.getSymbolName(StrTab, NamePair.second); if (std::error_code EC = NameOrErr.getError()) @@ -302,7 +306,11 @@ ErrorOr ELFDumper::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 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; -- 2.34.1