Skip to content

Commit edb6ab9

Browse files
committed
[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
1 parent 357a40e commit edb6ab9

File tree

3 files changed

+28
-16
lines changed

3 files changed

+28
-16
lines changed

llvm/include/llvm/Object/COFF.h

+4
Original file line numberDiff line numberDiff line change
@@ -1209,11 +1209,15 @@ class ResourceSectionRef {
12091209
Expected<const coff_resource_dir_table &>
12101210
getEntrySubDir(const coff_resource_dir_entry &Entry);
12111211
Expected<const coff_resource_dir_table &> getBaseTable();
1212+
Expected<const coff_resource_dir_entry &>
1213+
getTableEntry(const coff_resource_dir_table &Table, uint32_t Index);
12121214

12131215
private:
12141216
BinaryByteStream BBS;
12151217

12161218
Expected<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset);
1219+
Expected<const coff_resource_dir_entry &>
1220+
getTableEntryAtOffset(uint32_t Offset);
12171221
Expected<ArrayRef<UTF16>> getDirStringAtOffset(uint32_t Offset);
12181222
};
12191223

llvm/lib/Object/COFFObjectFile.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -1696,6 +1696,17 @@ ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
16961696
return *Table;
16971697
}
16981698

1699+
Expected<const coff_resource_dir_entry &>
1700+
ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) {
1701+
const coff_resource_dir_entry *Entry = nullptr;
1702+
1703+
BinaryStreamReader Reader(BBS);
1704+
Reader.setOffset(Offset);
1705+
RETURN_IF_ERROR(Reader.readObject(Entry));
1706+
assert(Entry != nullptr);
1707+
return *Entry;
1708+
}
1709+
16991710
Expected<const coff_resource_dir_table &>
17001711
ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
17011712
return getTableAtOffset(Entry.Offset.value());
@@ -1704,3 +1715,14 @@ ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
17041715
Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
17051716
return getTableAtOffset(0);
17061717
}
1718+
1719+
Expected<const coff_resource_dir_entry &>
1720+
ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table,
1721+
uint32_t Index) {
1722+
if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries))
1723+
return createStringError(object_error::parse_failed, "index out of range");
1724+
const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table);
1725+
ptrdiff_t TableOffset = TablePtr - BBS.data().data();
1726+
return getTableEntryAtOffset(TableOffset + sizeof(Table) +
1727+
Index * sizeof(coff_resource_dir_entry));
1728+
}

llvm/tools/llvm-readobj/COFFDumper.cpp

+2-16
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,6 @@ class COFFDumper : public ObjDumper {
171171
void printDelayImportedSymbols(
172172
const DelayImportDirectoryEntryRef &I,
173173
iterator_range<imported_symbol_iterator> Range);
174-
Expected<const coff_resource_dir_entry &>
175-
getResourceDirectoryTableEntry(const coff_resource_dir_table &Table,
176-
uint32_t Index);
177174

178175
typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy;
179176

@@ -1790,8 +1787,7 @@ COFFDumper::countTotalTableEntries(ResourceSectionRef RSF,
17901787
uint32_t TotalEntries = 0;
17911788
for (int i = 0; i < Table.NumberOfNameEntries + Table.NumberOfIDEntries;
17921789
i++) {
1793-
auto Entry = unwrapOrError(Obj->getFileName(),
1794-
getResourceDirectoryTableEntry(Table, i));
1790+
auto Entry = unwrapOrError(Obj->getFileName(), RSF.getTableEntry(Table, i));
17951791
if (Entry.Offset.isSubDir()) {
17961792
StringRef NextLevel;
17971793
if (Level == "Name")
@@ -1818,8 +1814,7 @@ void COFFDumper::printResourceDirectoryTable(
18181814
// Iterate through level in resource directory tree.
18191815
for (int i = 0; i < Table.NumberOfNameEntries + Table.NumberOfIDEntries;
18201816
i++) {
1821-
auto Entry = unwrapOrError(Obj->getFileName(),
1822-
getResourceDirectoryTableEntry(Table, i));
1817+
auto Entry = unwrapOrError(Obj->getFileName(), RSF.getTableEntry(Table, i));
18231818
StringRef Name;
18241819
SmallString<20> IDStr;
18251820
raw_svector_ostream OS(IDStr);
@@ -1873,15 +1868,6 @@ void COFFDumper::printResourceDirectoryTable(
18731868
}
18741869
}
18751870

1876-
Expected<const coff_resource_dir_entry &>
1877-
COFFDumper::getResourceDirectoryTableEntry(const coff_resource_dir_table &Table,
1878-
uint32_t Index) {
1879-
if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries))
1880-
return createError("can't get resource directory table entry");
1881-
auto TablePtr = reinterpret_cast<const coff_resource_dir_entry *>(&Table + 1);
1882-
return TablePtr[Index];
1883-
}
1884-
18851871
void COFFDumper::printStackMap() const {
18861872
object::SectionRef StackMapSection;
18871873
for (auto Sec : Obj->sections()) {

0 commit comments

Comments
 (0)