]> granicus.if.org Git - llvm/commitdiff
[Object] Verify object sizes before handing out StringRefs pointing out
authorBenjamin Kramer <benny.kra@googlemail.com>
Thu, 31 Aug 2017 12:27:10 +0000 (12:27 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Thu, 31 Aug 2017 12:27:10 +0000 (12:27 +0000)
of bounds.

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312235 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Object/Binary.h
include/llvm/Object/ELFObjectFile.h
lib/Object/COFFObjectFile.cpp
test/DebugInfo/Inputs/dwarfdump-decompression-corrupt.elf-x86-64 [new file with mode: 0644]
test/DebugInfo/dwarfdump-decompression-corrupt.test [new file with mode: 0644]

index 3f5a233c1ee185d8ba357e067b7cc0d54771e78b..d09879777e2cbf577c981c14d685a14bc49f649a 100644 (file)
@@ -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 @@ public:
       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.
index 73011f6f9fe1a0ca6579c67963b2deb0738ddcb1..f436e4534ce16a200e26639cdb64c7e19e934012 100644 (file)
@@ -667,6 +667,10 @@ std::error_code
 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();
 }
index 0a2053477caf180f6212171968be58b411b6b5df..f88ebfc9a1d231916f047ee8fe7277a175886b18 100644 (file)
@@ -52,16 +52,6 @@ static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
   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 @@ static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
                                  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 @@ getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
     // 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/test/DebugInfo/Inputs/dwarfdump-decompression-corrupt.elf-x86-64 b/test/DebugInfo/Inputs/dwarfdump-decompression-corrupt.elf-x86-64
new file mode 100644 (file)
index 0000000..d3b0b38
Binary files /dev/null and b/test/DebugInfo/Inputs/dwarfdump-decompression-corrupt.elf-x86-64 differ
diff --git a/test/DebugInfo/dwarfdump-decompression-corrupt.test b/test/DebugInfo/dwarfdump-decompression-corrupt.test
new file mode 100644 (file)
index 0000000..93f5360
--- /dev/null
@@ -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