[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
This commit is contained in:
Benjamin Kramer
2017-08-31 12:27:10 +00:00
parent 42f8bfc056
commit cbc7ee45f9
5 changed files with 24 additions and 12 deletions

View File

@@ -15,6 +15,7 @@
#define LLVM_OBJECT_BINARY_H #define LLVM_OBJECT_BINARY_H
#include "llvm/ADT/Triple.h" #include "llvm/ADT/Triple.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/Error.h" #include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include <algorithm> #include <algorithm>
@@ -143,6 +144,16 @@ public:
return Triple::ELF; return Triple::ELF;
return Triple::UnknownObjectFormat; 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. /// @brief Create a Binary from Source, autodetecting the file type.

View File

@@ -667,6 +667,10 @@ std::error_code
ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec, ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec,
StringRef &Result) const { StringRef &Result) const {
const Elf_Shdr *EShdr = getSection(Sec); 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); Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size);
return std::error_code(); return std::error_code();
} }

View File

@@ -52,16 +52,6 @@ static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
return true; 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. // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
// Returns unexpected_eof if error. // Returns unexpected_eof if error.
template <typename T> template <typename T>
@@ -69,7 +59,7 @@ static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
const void *Ptr, const void *Ptr,
const uint64_t Size = sizeof(T)) { const uint64_t Size = sizeof(T)) {
uintptr_t Addr = uintptr_t(Ptr); 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; return EC;
Obj = reinterpret_cast<const T *>(Addr); Obj = reinterpret_cast<const T *>(Addr);
return std::error_code(); return std::error_code();
@@ -383,7 +373,8 @@ getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
// relocations. // relocations.
begin++; 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 nullptr;
return begin; return begin;
} }

View File

@@ -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