[Object] Verify object sizes before handing out StringRefs pointing out
of bounds.

This can only happen on corrupt input. Found by OSS-FUZZ!
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3228

llvm-svn: 312235
diff --git a/llvm/include/llvm/Object/Binary.h b/llvm/include/llvm/Object/Binary.h
index 3f5a233..d098797 100644
--- a/llvm/include/llvm/Object/Binary.h
+++ b/llvm/include/llvm/Object/Binary.h
@@ -15,6 +15,7 @@
 #define LLVM_OBJECT_BINARY_H
 
 #include "llvm/ADT/Triple.h"
+#include "llvm/Object/Error.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include <algorithm>
@@ -143,6 +144,16 @@
       return Triple::ELF;
     return Triple::UnknownObjectFormat;
   }
+
+  static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr,
+                                     const uint64_t Size) {
+    if (Addr + Size < Addr || Addr + Size < Size ||
+        Addr + Size > uintptr_t(M.getBufferEnd()) ||
+        Addr < uintptr_t(M.getBufferStart())) {
+      return object_error::unexpected_eof;
+    }
+    return std::error_code();
+  }
 };
 
 /// @brief Create a Binary from Source, autodetecting the file type.
diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h
index 73011f6..f436e45 100644
--- a/llvm/include/llvm/Object/ELFObjectFile.h
+++ b/llvm/include/llvm/Object/ELFObjectFile.h
@@ -667,6 +667,10 @@
 ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec,
                                         StringRef &Result) const {
   const Elf_Shdr *EShdr = getSection(Sec);
+  if (std::error_code EC =
+          checkOffset(getMemoryBufferRef(),
+                      (uintptr_t)base() + EShdr->sh_offset, EShdr->sh_size))
+    return EC;
   Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size);
   return std::error_code();
 }
diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp
index 0a20534..f88ebfc 100644
--- a/llvm/lib/Object/COFFObjectFile.cpp
+++ b/llvm/lib/Object/COFFObjectFile.cpp
@@ -52,16 +52,6 @@
   return true;
 }
 
-static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr,
-                                   const uint64_t Size) {
-  if (Addr + Size < Addr || Addr + Size < Size ||
-      Addr + Size > uintptr_t(M.getBufferEnd()) ||
-      Addr < uintptr_t(M.getBufferStart())) {
-    return object_error::unexpected_eof;
-  }
-  return std::error_code();
-}
-
 // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
 // Returns unexpected_eof if error.
 template <typename T>
@@ -69,7 +59,7 @@
                                  const void *Ptr,
                                  const uint64_t Size = sizeof(T)) {
   uintptr_t Addr = uintptr_t(Ptr);
-  if (std::error_code EC = checkOffset(M, Addr, Size))
+  if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
     return EC;
   Obj = reinterpret_cast<const T *>(Addr);
   return std::error_code();
@@ -383,7 +373,8 @@
     // relocations.
     begin++;
   }
-  if (checkOffset(M, uintptr_t(begin), sizeof(coff_relocation) * NumRelocs))
+  if (Binary::checkOffset(M, uintptr_t(begin),
+                          sizeof(coff_relocation) * NumRelocs))
     return nullptr;
   return begin;
 }
diff --git a/llvm/test/DebugInfo/Inputs/dwarfdump-decompression-corrupt.elf-x86-64 b/llvm/test/DebugInfo/Inputs/dwarfdump-decompression-corrupt.elf-x86-64
new file mode 100644
index 0000000..d3b0b38
--- /dev/null
+++ b/llvm/test/DebugInfo/Inputs/dwarfdump-decompression-corrupt.elf-x86-64
Binary files differ
diff --git a/llvm/test/DebugInfo/dwarfdump-decompression-corrupt.test b/llvm/test/DebugInfo/dwarfdump-decompression-corrupt.test
new file mode 100644
index 0000000..93f5360
--- /dev/null
+++ b/llvm/test/DebugInfo/dwarfdump-decompression-corrupt.test
@@ -0,0 +1,6 @@
+REQUIRES: zlib
+
+// dwarfdump-decompression-corrupt.elf-x86-64 is fuzzer output
+RUN: llvm-dwarfdump %p/Inputs/dwarfdump-decompression-corrupt.elf-x86-64 2>&1 | FileCheck %s
+
+CHECK: error: failed to decompress '', corrupted compressed section header