[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:
@@ -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.
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
6
llvm/test/DebugInfo/dwarfdump-decompression-corrupt.test
Normal file
6
llvm/test/DebugInfo/dwarfdump-decompression-corrupt.test
Normal 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
|
||||||
Reference in New Issue
Block a user