diff options
author | Alexander Richardson <arichardson.kde@gmail.com> | 2017-10-05 23:28:29 +0000 |
---|---|---|
committer | Alexander Richardson <arichardson.kde@gmail.com> | 2017-10-05 23:28:29 +0000 |
commit | 57f089775b23cabdbafd5a84eebd78d830bf8d9d (patch) | |
tree | 1425fd877f99c2a92bdb7dfeedccd658b8229c43 | |
parent | b4e77d98ed9ccf8593667220b5bd022853691fad (diff) | |
download | bcm5719-llvm-57f089775b23cabdbafd5a84eebd78d830bf8d9d.tar.gz bcm5719-llvm-57f089775b23cabdbafd5a84eebd78d830bf8d9d.zip |
[ELF] Don't crash when parsing a file with external version definition references
Summary:
We were crashing when linking telnetd in FreeBSD because lld was emitting
corrupted output files for --norosegment. In this file the version index of some symbols
was set to 9 but lld only found 8 version definitions.
I am not sure how to create a minimal .so file that also exposes this behaviour so I just added the one that initially caused the error to Inputs/
This partially addresses https://bugs.llvm.org/show_bug.cgi?id=34705
Reviewers: ruiu, rafael, pcc, grimar
Reviewed By: ruiu
Subscribers: emaste, krytarowski
Tags: #lld
Differential Revision: https://reviews.llvm.org/D38397
llvm-svn: 315035
-rw-r--r-- | lld/ELF/InputFiles.cpp | 15 | ||||
-rw-r--r-- | lld/test/ELF/Inputs/corrupt-version-reference.so | bin | 0 -> 134272 bytes | |||
-rw-r--r-- | lld/test/ELF/corrupted-version-reference.s | 10 |
3 files changed, 22 insertions, 3 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index cfe8ae74ffa..a0a38de0d8a 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -775,9 +775,18 @@ template <class ELFT> void SharedFile<ELFT>::parseRest() { // Ignore local symbols. if (Versym && VersymIndex == VER_NDX_LOCAL) continue; - - const Elf_Verdef *V = - VersymIndex == VER_NDX_GLOBAL ? nullptr : Verdefs[VersymIndex]; + const Elf_Verdef *V = nullptr; + if (VersymIndex != VER_NDX_GLOBAL) { + if (VersymIndex >= Verdefs.size()) { + error("corrupt input file: version definition index " + + Twine(VersymIndex) + " for symbol " + Name + + " is greater than the maximum value " + + Twine(Verdefs.size() - 1) + "\n>>> symbol is defined in " + + toString(this)); + continue; + } + V = Verdefs[VersymIndex]; + } if (!Hidden) Symtab->addShared(Name, this, Sym, V); diff --git a/lld/test/ELF/Inputs/corrupt-version-reference.so b/lld/test/ELF/Inputs/corrupt-version-reference.so Binary files differnew file mode 100644 index 00000000000..ef6adc6a026 --- /dev/null +++ b/lld/test/ELF/Inputs/corrupt-version-reference.so diff --git a/lld/test/ELF/corrupted-version-reference.s b/lld/test/ELF/corrupted-version-reference.s new file mode 100644 index 00000000000..15fbbeeaa14 --- /dev/null +++ b/lld/test/ELF/corrupted-version-reference.s @@ -0,0 +1,10 @@ +# RUN: llvm-mc -triple=mips64-unknown-freebsd %s -filetype=obj -o %t.o +# RUN: not ld.lld %t.o %S/Inputs/corrupt-version-reference.so -o %t.exe 2>&1 | FileCheck %s + +# CHECK: error: corrupt input file: version definition index 9 for symbol __cxa_finalize is greater than the maximum value 8 +# CHECK: >>> symbol is defined in {{.+}}/corrupt-version-reference.so + +.globl __start +__start: + dla $a0, __cxa_finalize + nop |