[llvm] r312235 - [Object] Verify object sizes before handing out StringRefs pointing out

Benjamin Kramer via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 31 05:27:10 PDT 2017


Author: d0k
Date: Thu Aug 31 05:27:10 2017
New Revision: 312235

URL: http://llvm.org/viewvc/llvm-project?rev=312235&view=rev
Log:
[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

Added:
    llvm/trunk/test/DebugInfo/Inputs/dwarfdump-decompression-corrupt.elf-x86-64
    llvm/trunk/test/DebugInfo/dwarfdump-decompression-corrupt.test
Modified:
    llvm/trunk/include/llvm/Object/Binary.h
    llvm/trunk/include/llvm/Object/ELFObjectFile.h
    llvm/trunk/lib/Object/COFFObjectFile.cpp

Modified: llvm/trunk/include/llvm/Object/Binary.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/Binary.h?rev=312235&r1=312234&r2=312235&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/Binary.h (original)
+++ llvm/trunk/include/llvm/Object/Binary.h Thu Aug 31 05:27:10 2017
@@ -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.

Modified: llvm/trunk/include/llvm/Object/ELFObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELFObjectFile.h?rev=312235&r1=312234&r2=312235&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ELFObjectFile.h (original)
+++ llvm/trunk/include/llvm/Object/ELFObjectFile.h Thu Aug 31 05:27:10 2017
@@ -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();
 }

Modified: llvm/trunk/lib/Object/COFFObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/COFFObjectFile.cpp?rev=312235&r1=312234&r2=312235&view=diff
==============================================================================
--- llvm/trunk/lib/Object/COFFObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/COFFObjectFile.cpp Thu Aug 31 05:27:10 2017
@@ -52,16 +52,6 @@ static bool checkSize(MemoryBufferRef M,
   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
                                  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, M
     // 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;
 }

Added: llvm/trunk/test/DebugInfo/Inputs/dwarfdump-decompression-corrupt.elf-x86-64
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/Inputs/dwarfdump-decompression-corrupt.elf-x86-64?rev=312235&view=auto
==============================================================================
Binary files llvm/trunk/test/DebugInfo/Inputs/dwarfdump-decompression-corrupt.elf-x86-64 (added) and llvm/trunk/test/DebugInfo/Inputs/dwarfdump-decompression-corrupt.elf-x86-64 Thu Aug 31 05:27:10 2017 differ

Added: llvm/trunk/test/DebugInfo/dwarfdump-decompression-corrupt.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/dwarfdump-decompression-corrupt.test?rev=312235&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/dwarfdump-decompression-corrupt.test (added)
+++ llvm/trunk/test/DebugInfo/dwarfdump-decompression-corrupt.test Thu Aug 31 05:27:10 2017
@@ -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




More information about the llvm-commits mailing list