From 1a7f03ef84da74bfde2dfe8d9d8ef530ad390da4 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Thu, 31 Aug 2017 12:27:10 +0000 Subject: [PATCH] [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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312235 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/Binary.h | 11 +++++++++++ include/llvm/Object/ELFObjectFile.h | 4 ++++ lib/Object/COFFObjectFile.cpp | 15 +++------------ .../dwarfdump-decompression-corrupt.elf-x86-64 | Bin 0 -> 120 bytes .../dwarfdump-decompression-corrupt.test | 6 ++++++ 5 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 test/DebugInfo/Inputs/dwarfdump-decompression-corrupt.elf-x86-64 create mode 100644 test/DebugInfo/dwarfdump-decompression-corrupt.test diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 3f5a233c1ee..d09879777e2 100644 --- a/include/llvm/Object/Binary.h +++ b/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 @@ -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. diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 73011f6f9fe..f436e4534ce 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -667,6 +667,10 @@ std::error_code ELFObjectFile::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/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 0a2053477ca..f88ebfc9a1d 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -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 @@ -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(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 index 0000000000000000000000000000000000000000..d3b0b38a92f2c180d843aaa410e805d323be576d GIT binary patch literal 120 ucmb<-^>JflR6v0L{}uitcnTT}3=9aa1_Kj_{~xFb2LMV#)Z&1 | FileCheck %s + +CHECK: error: failed to decompress '', corrupted compressed section header -- 2.50.1