[COFF] Bounds check relocations
Summary:
This would have caught the invalid object file I used in my test case in
r307726. The OOB was only caught by ASan later, which is slow and
doesn't work on some platforms. LLD should do some basic input
validation itself. This check isn't perfect, so relocations can reach
OOB by up to seven bytes, but it's better than what we had and probably
cheap.
Reviewers: ruiu
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D35371
llvm-svn: 307948
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index c0996f5..3f6f49b 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -210,7 +210,15 @@
memcpy(Buf + OutputSectionOff, A.data(), A.size());
// Apply relocations.
+ size_t InputSize = getSize();
for (const coff_relocation &Rel : Relocs) {
+ // Check for an invalid relocation offset. This check isn't perfect, because
+ // we don't have the relocation size, which is only known after checking the
+ // machine and relocation type. As a result, a relocation may overwrite the
+ // beginning of the following input section.
+ if (Rel.VirtualAddress >= InputSize)
+ fatal("relocation points beyond the end of its parent section");
+
uint8_t *Off = Buf + OutputSectionOff + Rel.VirtualAddress;
// Get the output section of the symbol for this relocation. The output