From edb6ab9ba66c8fa751e47a4fc87f323f614070de Mon Sep 17 00:00:00 2001 From: Martin Storsjo Date: Thu, 29 Aug 2019 08:59:56 +0000 Subject: [PATCH] [COFF] Add a bounds checking helper for iterating a coff_resource_dir_table Instead of blindly incrementing pointers in llvm-readobj, use this helper, which does bounds checking against the available section data. Differential Revision: https://reviews.llvm.org/D66818 llvm-svn: 370310 --- llvm/include/llvm/Object/COFF.h | 4 ++++ llvm/lib/Object/COFFObjectFile.cpp | 22 ++++++++++++++++++++++ llvm/tools/llvm-readobj/COFFDumper.cpp | 18 ++---------------- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/llvm/include/llvm/Object/COFF.h b/llvm/include/llvm/Object/COFF.h index 5f6e22014dca..f0112167b3a1 100644 --- a/llvm/include/llvm/Object/COFF.h +++ b/llvm/include/llvm/Object/COFF.h @@ -1209,11 +1209,15 @@ public: Expected getEntrySubDir(const coff_resource_dir_entry &Entry); Expected getBaseTable(); + Expected + getTableEntry(const coff_resource_dir_table &Table, uint32_t Index); private: BinaryByteStream BBS; Expected getTableAtOffset(uint32_t Offset); + Expected + getTableEntryAtOffset(uint32_t Offset); Expected> getDirStringAtOffset(uint32_t Offset); }; diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp index b3dbf75a5c32..368a6d10344f 100644 --- a/llvm/lib/Object/COFFObjectFile.cpp +++ b/llvm/lib/Object/COFFObjectFile.cpp @@ -1696,6 +1696,17 @@ ResourceSectionRef::getTableAtOffset(uint32_t Offset) { return *Table; } +Expected +ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) { + const coff_resource_dir_entry *Entry = nullptr; + + BinaryStreamReader Reader(BBS); + Reader.setOffset(Offset); + RETURN_IF_ERROR(Reader.readObject(Entry)); + assert(Entry != nullptr); + return *Entry; +} + Expected ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) { return getTableAtOffset(Entry.Offset.value()); @@ -1704,3 +1715,14 @@ ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) { Expected ResourceSectionRef::getBaseTable() { return getTableAtOffset(0); } + +Expected +ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table, + uint32_t Index) { + if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries)) + return createStringError(object_error::parse_failed, "index out of range"); + const uint8_t *TablePtr = reinterpret_cast(&Table); + ptrdiff_t TableOffset = TablePtr - BBS.data().data(); + return getTableEntryAtOffset(TableOffset + sizeof(Table) + + Index * sizeof(coff_resource_dir_entry)); +} diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp index 6b5564aebfc3..7d3d093d2e9f 100644 --- a/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/llvm/tools/llvm-readobj/COFFDumper.cpp @@ -171,9 +171,6 @@ private: void printDelayImportedSymbols( const DelayImportDirectoryEntryRef &I, iterator_range Range); - Expected - getResourceDirectoryTableEntry(const coff_resource_dir_table &Table, - uint32_t Index); typedef DenseMap > RelocMapTy; @@ -1790,8 +1787,7 @@ COFFDumper::countTotalTableEntries(ResourceSectionRef RSF, uint32_t TotalEntries = 0; for (int i = 0; i < Table.NumberOfNameEntries + Table.NumberOfIDEntries; i++) { - auto Entry = unwrapOrError(Obj->getFileName(), - getResourceDirectoryTableEntry(Table, i)); + auto Entry = unwrapOrError(Obj->getFileName(), RSF.getTableEntry(Table, i)); if (Entry.Offset.isSubDir()) { StringRef NextLevel; if (Level == "Name") @@ -1818,8 +1814,7 @@ void COFFDumper::printResourceDirectoryTable( // Iterate through level in resource directory tree. for (int i = 0; i < Table.NumberOfNameEntries + Table.NumberOfIDEntries; i++) { - auto Entry = unwrapOrError(Obj->getFileName(), - getResourceDirectoryTableEntry(Table, i)); + auto Entry = unwrapOrError(Obj->getFileName(), RSF.getTableEntry(Table, i)); StringRef Name; SmallString<20> IDStr; raw_svector_ostream OS(IDStr); @@ -1873,15 +1868,6 @@ void COFFDumper::printResourceDirectoryTable( } } -Expected -COFFDumper::getResourceDirectoryTableEntry(const coff_resource_dir_table &Table, - uint32_t Index) { - if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries)) - return createError("can't get resource directory table entry"); - auto TablePtr = reinterpret_cast(&Table + 1); - return TablePtr[Index]; -} - void COFFDumper::printStackMap() const { object::SectionRef StackMapSection; for (auto Sec : Obj->sections()) {