Skip to content

Commit f7cfabb

Browse files
committedJun 14, 2019
[llvm-readobj] Don't abort printing of dynamic table if string reference is invalid
If dynamic table is missing, output "dynamic strtab not found'. If the index is out of range, output "Invalid Offset<..>". https://bugs.llvm.org/show_bug.cgi?id=40807 Reviewed by: jhenderson, grimar, MaskRay Differential Revision: https://reviews.llvm.org/D63084 Patch by Yuanfang Chen. llvm-svn: 363374
1 parent 78b2cf7 commit f7cfabb

File tree

4 files changed

+81
-41
lines changed

4 files changed

+81
-41
lines changed
 
-1.67 KB
Binary file not shown.

Diff for: ‎llvm/test/Object/corrupt.test

-7
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,6 @@ RUN: 2>&1 | FileCheck --check-prefix=VER %s
2525

2626
VER: error: Invalid version entry
2727

28-
29-
// The file is missing the dynamic string table but has references to it.
30-
RUN: not llvm-readobj --dynamic-table %p/Inputs/corrupt-invalid-strtab.elf.x86-64 \
31-
RUN: 2>&1 | FileCheck --check-prefix=STRTAB %s
32-
33-
STRTAB: Invalid dynamic string table reference
34-
3528
RUN: not llvm-readobj -l \
3629
RUN: %p/Inputs/corrupt-invalid-phentsize.elf.x86-64 2>&1 | \
3730
RUN: FileCheck --check-prefix=PHENTSIZE %s

Diff for: ‎llvm/test/tools/llvm-readobj/elf-dynamic-malformed.test

+44-9
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,28 @@ ProgramHeaders:
6868
Sections:
6969
- Section: .dynamic
7070

71-
# Test handling of string references pointing past the end of the dynamic string table. In this case,
72-
# we have a DT_NEEDED tag pointing at offset 1 in a 1-byte string table.
71+
# Test handling of string references pointing past the end of the dynamic string table.
7372
# RUN: yaml2obj %s --docnum=3 -o %t.bad-string
74-
# RUN: not llvm-readobj --dynamic-table %t.bad-string 2>&1 | FileCheck %s --check-prefix BAD-STRING
75-
# RUN: not llvm-readelf --dynamic-table %t.bad-string 2>&1 | FileCheck %s --check-prefix BAD-STRING
73+
# RUN: llvm-readobj --dynamic-table %t.bad-string | FileCheck %s --check-prefix BAD-STRING-LLVM
74+
# RUN: llvm-readelf --dynamic-table %t.bad-string | FileCheck %s --check-prefix BAD-STRING-GNU
7675

77-
# BAD-STRING: Invalid dynamic string table reference
76+
# BAD-STRING-LLVM: 0x000000000000000A STRSZ 1 (bytes)
77+
# BAD-STRING-LLVM: 0x0000000000000001 NEEDED Shared library: <Invalid offset 0x1>
78+
# BAD-STRING-LLVM: 0x000000007FFFFFFF FILTER Filter library: <Invalid offset 0x1>
79+
# BAD-STRING-LLVM: 0x000000007FFFFFFD AUXILIARY Auxiliary library: <Invalid offset 0x1>
80+
# BAD-STRING-LLVM: 0x000000007FFFFFFE USED Not needed object: <Invalid offset 0x1>
81+
# BAD-STRING-LLVM: 0x000000000000000E SONAME Library soname: <Invalid offset 0x1>
82+
# BAD-STRING-LLVM: 0x000000000000000F RPATH <Invalid offset 0x1>
83+
# BAD-STRING-LLVM: 0x000000000000001D RUNPATH <Invalid offset 0x1>
84+
85+
# BAD-STRING-GNU: 0x000000000000000a (STRSZ) 1 (bytes)
86+
# BAD-STRING-GNU: 0x0000000000000001 (NEEDED) Shared library: <Invalid offset 0x1>
87+
# BAD-STRING-GNU: 0x000000007fffffff (FILTER) Filter library: <Invalid offset 0x1>
88+
# BAD-STRING-GNU: 0x000000007ffffffd (AUXILIARY) Auxiliary library: <Invalid offset 0x1>
89+
# BAD-STRING-GNU: 0x000000007ffffffe (USED) Not needed object: <Invalid offset 0x1>
90+
# BAD-STRING-GNU: 0x000000000000000e (SONAME) Library soname: <Invalid offset 0x1>
91+
# BAD-STRING-GNU: 0x000000000000000f (RPATH) <Invalid offset 0x1>
92+
# BAD-STRING-GNU: 0x000000000000001d (RUNPATH) <Invalid offset 0x1>
7893

7994
--- !ELF
8095
FileHeader:
@@ -96,6 +111,18 @@ Sections:
96111
Value: 1
97112
- Tag: DT_NEEDED
98113
Value: 1
114+
- Tag: DT_FILTER
115+
Value: 1
116+
- Tag: DT_AUXILIARY
117+
Value: 1
118+
- Tag: DT_USED
119+
Value: 1
120+
- Tag: DT_SONAME
121+
Value: 1
122+
- Tag: DT_RPATH
123+
Value: 1
124+
- Tag: DT_RUNPATH
125+
Value: 1
99126
- Tag: DT_NULL
100127
Value: 0
101128
ProgramHeaders:
@@ -111,11 +138,19 @@ ProgramHeaders:
111138

112139
# Test handling of DT_STRTAB pointing outside the file's address space.
113140
# RUN: yaml2obj %s --docnum=4 -o %t.bad-strtab
114-
# RUN: not llvm-readobj --dynamic-table %t.bad-strtab 2>&1 | FileCheck %s --check-prefix BAD-STRTAB
115-
# RUN: not llvm-readelf --dynamic-table %t.bad-strtab 2>&1 | FileCheck %s --check-prefix BAD-STRTAB
116141

117-
# BAD-STRTAB: warning: Unable to parse DT_STRTAB: Virtual address is not in any segment
118-
# BAD-STRTAB: error: Invalid dynamic string table reference
142+
# RUN: llvm-readobj --dynamic-table %t.bad-strtab 2>&1 >/dev/null | FileCheck %s --check-prefix BAD-STRTAB-ERR
143+
# RUN: llvm-readelf --dynamic-table %t.bad-strtab 2>&1 >/dev/null | FileCheck %s --check-prefix BAD-STRTAB-ERR
144+
# BAD-STRTAB-ERR: warning: Unable to parse DT_STRTAB: Virtual address is not in any segment
145+
146+
# RUN: llvm-readobj --dynamic-table --needed-libs %t.bad-strtab | FileCheck %s --check-prefixes=BAD-STRTAB,BAD-STRTAB-LLVM
147+
# RUN: llvm-readelf --dynamic-table --needed-libs %t.bad-strtab | FileCheck %s --check-prefixes=BAD-STRTAB,BAD-STRTAB-GNU
148+
# BAD-STRTAB-LLVM: LoadName: <Not found>
149+
# BAD-STRTAB-LLVM: 0x0000000000000001 NEEDED Shared library: <String table is empty or was not found>
150+
# BAD-STRTAB-GNU: 0x0000000000000001 (NEEDED) Shared library: <String table is empty or was not found>
151+
# BAD-STRTAB: NeededLibraries [
152+
# BAD-STRTAB: <Library name index out of range>
153+
# BAD-STRTAB: ]
119154

120155
--- !ELF
121156
FileHeader:

Diff for: ‎llvm/tools/llvm-readobj/ELFDumper.cpp

+37-25
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,8 @@ template <typename ELFT> class ELFDumper : public ObjDumper {
206206
void loadDynamicTable(const ELFFile<ELFT> *Obj);
207207
void parseDynamicTable();
208208

209-
StringRef getDynamicString(uint64_t Offset) const;
209+
void printDynamicString(uint64_t Offset, raw_ostream &OS,
210+
bool WithBracket = true) const;
210211
StringRef getSymbolVersion(StringRef StrTab, const Elf_Sym *symb,
211212
bool &IsDefault) const;
212213
void LoadVersionMap() const;
@@ -221,7 +222,7 @@ template <typename ELFT> class ELFDumper : public ObjDumper {
221222
DynRegionInfo DynSymRegion;
222223
DynRegionInfo DynamicTable;
223224
StringRef DynamicStringTable;
224-
StringRef SOName;
225+
StringRef SOName = "<Not found>";
225226
const Elf_Hash *HashTable = nullptr;
226227
const Elf_GnuHash *GnuHashTable = nullptr;
227228
const Elf_Shdr *DotSymtabSec = nullptr;
@@ -1626,8 +1627,8 @@ template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {
16261627
}
16271628
if (StringTableBegin)
16281629
DynamicStringTable = StringRef(StringTableBegin, StringTableSize);
1629-
if (SONameOffset)
1630-
SOName = getDynamicString(SONameOffset);
1630+
if (SONameOffset && SONameOffset < DynamicStringTable.size())
1631+
SOName = DynamicStringTable.data() + SONameOffset;
16311632
}
16321633

16331634
template <typename ELFT>
@@ -1790,14 +1791,19 @@ void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) {
17901791
}
17911792

17921793
template <class ELFT>
1793-
StringRef ELFDumper<ELFT>::getDynamicString(uint64_t Value) const {
1794-
if (Value >= DynamicStringTable.size())
1795-
reportError("Invalid dynamic string table reference");
1796-
return StringRef(DynamicStringTable.data() + Value);
1797-
}
1798-
1799-
static void printLibrary(raw_ostream &OS, const Twine &Tag, const Twine &Name) {
1800-
OS << Tag << ": [" << Name << "]";
1794+
void ELFDumper<ELFT>::printDynamicString(uint64_t Value,
1795+
raw_ostream &OS,
1796+
bool WithBracket) const {
1797+
if (DynamicStringTable.empty())
1798+
OS << "<String table is empty or was not found> ";
1799+
else if (Value < DynamicStringTable.size()) {
1800+
if (WithBracket)
1801+
OS << "[";
1802+
OS << StringRef(DynamicStringTable.data() + Value);
1803+
if (WithBracket)
1804+
OS << "]";
1805+
} else
1806+
OS << "<Invalid offset 0x" << utohexstr(Value) << ">";
18011807
}
18021808

18031809
template <class ELFT>
@@ -1943,23 +1949,24 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
19431949
OS << Value << " (bytes)";
19441950
break;
19451951
case DT_NEEDED:
1946-
printLibrary(OS, "Shared library", getDynamicString(Value));
1947-
break;
19481952
case DT_SONAME:
1949-
printLibrary(OS, "Library soname", getDynamicString(Value));
1950-
break;
19511953
case DT_AUXILIARY:
1952-
printLibrary(OS, "Auxiliary library", getDynamicString(Value));
1953-
break;
19541954
case DT_USED:
1955-
printLibrary(OS, "Not needed object", getDynamicString(Value));
1956-
break;
1957-
case DT_FILTER:
1958-
printLibrary(OS, "Filter library", getDynamicString(Value));
1955+
case DT_FILTER: {
1956+
const std::map<uint64_t, const char*> TagNames = {
1957+
{DT_NEEDED, "Shared library"},
1958+
{DT_SONAME, "Library soname"},
1959+
{DT_AUXILIARY, "Auxiliary library"},
1960+
{DT_USED, "Not needed object"},
1961+
{DT_FILTER, "Filter library"},
1962+
};
1963+
OS << TagNames.at(Type) << ": ";
1964+
printDynamicString(Value, OS);
19591965
break;
1966+
}
19601967
case DT_RPATH:
19611968
case DT_RUNPATH:
1962-
OS << getDynamicString(Value);
1969+
printDynamicString(Value, OS, false);
19631970
break;
19641971
case DT_FLAGS:
19651972
printFlags(Value, makeArrayRef(ElfDynamicDTFlags), OS);
@@ -2004,8 +2011,13 @@ template <class ELFT> void ELFDumper<ELFT>::printNeededLibraries() {
20042011
LibsTy Libs;
20052012

20062013
for (const auto &Entry : dynamic_table())
2007-
if (Entry.d_tag == ELF::DT_NEEDED)
2008-
Libs.push_back(getDynamicString(Entry.d_un.d_val));
2014+
if (Entry.d_tag == ELF::DT_NEEDED) {
2015+
uint64_t Value = Entry.d_un.d_val;
2016+
if (Value < DynamicStringTable.size())
2017+
Libs.push_back(StringRef(DynamicStringTable.data() + Value));
2018+
else
2019+
Libs.push_back("<Library name index out of range>");
2020+
}
20092021

20102022
llvm::stable_sort(Libs);
20112023

0 commit comments

Comments
 (0)
Please sign in to comment.