mirror of
https://github.com/claunia/flac.git
synced 2025-12-16 18:54:26 +00:00
oss-fuzz: Add fuzzing headers
These includes header files were taken from:
https://github.com/guidovranken/fuzzing-headers.git
with some minor changes required to make them compile cleanly
with the extra compiler warning flags used by the FLAC build
system.
This commit is contained in:
6
oss-fuzz/fuzzing/Readme.md
Normal file
6
oss-fuzz/fuzzing/Readme.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
The header files in this directory and below were taken from:
|
||||||
|
|
||||||
|
https://github.com/guidovranken/fuzzing-headers.git
|
||||||
|
|
||||||
|
Some minor modifications were made to make them build with the default C++
|
||||||
|
warning flags.
|
||||||
167
oss-fuzz/fuzzing/datasource/datasource.hpp
Normal file
167
oss-fuzz/fuzzing/datasource/datasource.hpp
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fuzzing/exception.hpp>
|
||||||
|
#include <fuzzing/types.hpp>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace fuzzing {
|
||||||
|
namespace datasource {
|
||||||
|
|
||||||
|
class Base
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
virtual std::vector<uint8_t> get(const size_t min, const size_t max, const uint64_t id = 0) = 0;
|
||||||
|
public:
|
||||||
|
Base(void) = default;
|
||||||
|
virtual ~Base(void) = default;
|
||||||
|
|
||||||
|
template<class T> T Get(const uint64_t id = 0);
|
||||||
|
uint16_t GetChoice(const uint64_t id = 0);
|
||||||
|
std::vector<uint8_t> GetData(const uint64_t id, const size_t min = 0, const size_t max = 0);
|
||||||
|
template <class T> std::vector<T> GetVector(const uint64_t id = 0);
|
||||||
|
|
||||||
|
class OutOfData : public fuzzing::exception::FlowException {
|
||||||
|
public:
|
||||||
|
OutOfData() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DeserializationFailure : public fuzzing::exception::FlowException {
|
||||||
|
public:
|
||||||
|
DeserializationFailure() = default;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef FUZZING_HEADERS_NO_IMPL
|
||||||
|
template<class T> T Base::Get(const uint64_t id)
|
||||||
|
{
|
||||||
|
T ret;
|
||||||
|
const auto v = get(sizeof(ret), sizeof(ret), id);
|
||||||
|
memcpy(&ret, v.data(), sizeof(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> bool Base::Get<bool>(const uint64_t id)
|
||||||
|
{
|
||||||
|
uint8_t ret;
|
||||||
|
const auto v = get(sizeof(ret), sizeof(ret), id);
|
||||||
|
memcpy(&ret, v.data(), sizeof(ret));
|
||||||
|
return (ret % 2) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> std::string Base::Get<std::string>(const uint64_t id)
|
||||||
|
{
|
||||||
|
auto data = GetData(id);
|
||||||
|
return std::string(data.data(), data.data() + data.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> std::vector<std::string> Base::Get<std::vector<std::string>>(const uint64_t id)
|
||||||
|
{
|
||||||
|
std::vector<std::string> ret;
|
||||||
|
while ( true ) {
|
||||||
|
auto data = GetData(id);
|
||||||
|
ret.push_back( std::string(data.data(), data.data() + data.size()) );
|
||||||
|
if ( Get<bool>(id) == false ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t Base::GetChoice(const uint64_t id)
|
||||||
|
{
|
||||||
|
return Get<uint16_t>(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> Base::GetData(const uint64_t id, const size_t min, const size_t max)
|
||||||
|
{
|
||||||
|
return get(min, max, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <> types::String<> Base::Get<types::String<>>(const uint64_t id) {
|
||||||
|
const auto data = GetData(id);
|
||||||
|
types::String<> ret(data.data(), data.size());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> types::Data<> Base::Get<types::Data<>>(const uint64_t id) {
|
||||||
|
const auto data = GetData(id);
|
||||||
|
types::Data<> ret(data.data(), data.size());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
std::vector<T> Base::GetVector(const uint64_t id) {
|
||||||
|
std::vector<T> ret;
|
||||||
|
|
||||||
|
while ( Get<bool>(id) == true ) {
|
||||||
|
ret.push_back( Get<T>(id) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class Datasource : public Base
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const uint8_t* data;
|
||||||
|
const size_t size;
|
||||||
|
size_t idx;
|
||||||
|
size_t left;
|
||||||
|
std::vector<uint8_t> get(const size_t min, const size_t max, const uint64_t id = 0) override;
|
||||||
|
|
||||||
|
// Make copy constructor and assignment opertator private.
|
||||||
|
Datasource(const Datasource &) : data(0), size(0), idx(0), left(0) {}
|
||||||
|
Datasource& operator=(const Datasource &) { return *this; }
|
||||||
|
public:
|
||||||
|
Datasource(const uint8_t* _data, const size_t _size);
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef FUZZING_HEADERS_NO_IMPL
|
||||||
|
Datasource::Datasource(const uint8_t* _data, const size_t _size) :
|
||||||
|
Base(), data(_data), size(_size), idx(0), left(size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> Datasource::get(const size_t min, const size_t max, const uint64_t id) {
|
||||||
|
(void)id;
|
||||||
|
|
||||||
|
uint32_t getSize;
|
||||||
|
if ( left < sizeof(getSize) ) {
|
||||||
|
throw OutOfData();
|
||||||
|
}
|
||||||
|
memcpy(&getSize, data + idx, sizeof(getSize));
|
||||||
|
idx += sizeof(getSize);
|
||||||
|
left -= sizeof(getSize);
|
||||||
|
|
||||||
|
if ( getSize < min ) {
|
||||||
|
getSize = min;
|
||||||
|
}
|
||||||
|
if ( max && getSize > max ) {
|
||||||
|
getSize = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( left < getSize ) {
|
||||||
|
throw OutOfData();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> ret(getSize);
|
||||||
|
|
||||||
|
if ( getSize > 0 ) {
|
||||||
|
memcpy(ret.data(), data + idx, getSize);
|
||||||
|
}
|
||||||
|
idx += getSize;
|
||||||
|
left -= getSize;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} /* namespace datasource */
|
||||||
|
} /* namespace fuzzing */
|
||||||
52
oss-fuzz/fuzzing/datasource/id.hpp
Normal file
52
oss-fuzz/fuzzing/datasource/id.hpp
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <utility>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace fuzzing {
|
||||||
|
namespace datasource {
|
||||||
|
|
||||||
|
/* From: https://gist.github.com/underscorediscovery/81308642d0325fd386237cfa3b44785c */
|
||||||
|
inline uint64_t hash_64_fnv1a(const void* key, const uint64_t len) {
|
||||||
|
|
||||||
|
const char* data = (char*)key;
|
||||||
|
uint64_t hash = 0xcbf29ce484222325;
|
||||||
|
uint64_t prime = 0x100000001b3;
|
||||||
|
|
||||||
|
for(uint64_t i = 0; i < len; ++i) {
|
||||||
|
uint8_t value = data[i];
|
||||||
|
hash = hash ^ value;
|
||||||
|
hash *= prime;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
|
||||||
|
} //hash_64_fnv1a
|
||||||
|
|
||||||
|
// FNV1a c++11 constexpr compile time hash functions, 32 and 64 bit
|
||||||
|
// str should be a null terminated string literal, value should be left out
|
||||||
|
// e.g hash_32_fnv1a_const("example")
|
||||||
|
// code license: public domain or equivalent
|
||||||
|
// post: https://notes.underscorediscovery.com/constexpr-fnv1a/
|
||||||
|
|
||||||
|
constexpr uint32_t val_32_const = 0x811c9dc5;
|
||||||
|
constexpr uint32_t prime_32_const = 0x1000193;
|
||||||
|
constexpr uint64_t val_64_const = 0xcbf29ce484222325;
|
||||||
|
constexpr uint64_t prime_64_const = 0x100000001b3;
|
||||||
|
|
||||||
|
|
||||||
|
inline constexpr uint64_t ID(const char* const str, const uint64_t value = val_64_const) noexcept {
|
||||||
|
auto ret = (str[0] == '\0') ? value : ID(&str[1], (value ^ uint64_t(str[0])) * prime_64_const);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr std::pair<const char*, uint64_t> IDPair(const char* const str, const uint64_t value = val_64_const) noexcept {
|
||||||
|
return {str, ID(str, value)};
|
||||||
|
}
|
||||||
|
|
||||||
|
using IDMap = std::map<const char*, uint64_t>;
|
||||||
|
|
||||||
|
} /* namespace datasource */
|
||||||
|
} /* namespace fuzzing */
|
||||||
44
oss-fuzz/fuzzing/exception.hpp
Normal file
44
oss-fuzz/fuzzing/exception.hpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace fuzzing {
|
||||||
|
namespace exception {
|
||||||
|
|
||||||
|
class ExceptionBase : public std::exception {
|
||||||
|
public:
|
||||||
|
ExceptionBase(void) = default;
|
||||||
|
/* typeid(T).name */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Recoverable exception */
|
||||||
|
class FlowException : public ExceptionBase {
|
||||||
|
public:
|
||||||
|
FlowException(void) : ExceptionBase() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Error in this library, should never happen */
|
||||||
|
class LogicException : public ExceptionBase {
|
||||||
|
private:
|
||||||
|
std::string reason;
|
||||||
|
public:
|
||||||
|
LogicException(const std::string r) : ExceptionBase(), reason(r) { }
|
||||||
|
virtual const char* what(void) const throw() {
|
||||||
|
return reason.c_str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Error in target application */
|
||||||
|
class TargetException : public ExceptionBase {
|
||||||
|
private:
|
||||||
|
std::string reason;
|
||||||
|
public:
|
||||||
|
TargetException(const std::string r) : ExceptionBase(), reason(r) { }
|
||||||
|
virtual const char* what(void) const throw() {
|
||||||
|
return reason.c_str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace exception */
|
||||||
|
} /* namespace fuzzing */
|
||||||
73
oss-fuzz/fuzzing/memory.hpp
Normal file
73
oss-fuzz/fuzzing/memory.hpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#ifndef ASAN
|
||||||
|
#define ASAN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MSAN
|
||||||
|
#define MSAN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace fuzzing {
|
||||||
|
namespace memory {
|
||||||
|
|
||||||
|
#ifndef FUZZING_HEADERS_NO_IMPL
|
||||||
|
#if ASAN == 1
|
||||||
|
extern "C" void *__asan_region_is_poisoned(const void *beg, size_t size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MSAN == 1
|
||||||
|
extern "C" void __msan_check_mem_is_initialized(const volatile void *x, size_t size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void memory_test_asan(const void* data, const size_t size)
|
||||||
|
{
|
||||||
|
(void)data;
|
||||||
|
(void)size;
|
||||||
|
|
||||||
|
#if ASAN == 1
|
||||||
|
if ( __asan_region_is_poisoned(data, size) != NULL ) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void memory_test_msan(const void* data, const size_t size)
|
||||||
|
{
|
||||||
|
(void)data;
|
||||||
|
(void)size;
|
||||||
|
|
||||||
|
#if MSAN == 1
|
||||||
|
__msan_check_mem_is_initialized(data, size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void memory_test(const void* data, const size_t size)
|
||||||
|
{
|
||||||
|
memory_test_asan(data, size);
|
||||||
|
memory_test_msan(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void memory_test(const T& t)
|
||||||
|
{
|
||||||
|
(void)t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void memory_test(const std::string& s)
|
||||||
|
{
|
||||||
|
(void)s;
|
||||||
|
|
||||||
|
#if MSAN == 1
|
||||||
|
memory_test(s.data(), s.size());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} /* namespace memory */
|
||||||
|
} /* namespace fuzzing */
|
||||||
135
oss-fuzz/fuzzing/types.hpp
Normal file
135
oss-fuzz/fuzzing/types.hpp
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <fuzzing/memory.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace fuzzing {
|
||||||
|
namespace types {
|
||||||
|
|
||||||
|
template <typename CoreType, bool NullTerminated, bool UseMSAN = false>
|
||||||
|
class Container {
|
||||||
|
private:
|
||||||
|
CoreType* InvalidAddress = (CoreType*)0x12;
|
||||||
|
|
||||||
|
CoreType* _data = InvalidAddress;
|
||||||
|
size_t _size = 0;
|
||||||
|
|
||||||
|
#ifndef FUZZING_HEADERS_NO_IMPL
|
||||||
|
void copy(const void* data, size_t size) {
|
||||||
|
if ( size > 0 ) {
|
||||||
|
std::memcpy(_data, data, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void allocate(size_t size) {
|
||||||
|
if ( size > 0 ) {
|
||||||
|
_data = static_cast<CoreType*>(malloc(size * sizeof(CoreType)));
|
||||||
|
} else {
|
||||||
|
_data = InvalidAddress;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void allocate_and_copy(const void* data, size_t size) {
|
||||||
|
allocate(size);
|
||||||
|
copy(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void allocate_plus_1_and_copy(const void* data, size_t size) {
|
||||||
|
allocate(size+1);
|
||||||
|
copy(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void access_hook(void) const {
|
||||||
|
if ( UseMSAN == true ) {
|
||||||
|
memory::memory_test_msan(_data, _size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(void) {
|
||||||
|
access_hook();
|
||||||
|
|
||||||
|
if ( _data != InvalidAddress ) {
|
||||||
|
std::free(_data);
|
||||||
|
_data = InvalidAddress;
|
||||||
|
_size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
#ifndef FUZZING_HEADERS_NO_IMPL
|
||||||
|
CoreType* data(void) {
|
||||||
|
access_hook();
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size(void) const {
|
||||||
|
access_hook();
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Container(void)
|
||||||
|
#ifndef FUZZING_HEADERS_NO_IMPL
|
||||||
|
= default
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
Container(const void* data, const size_t size)
|
||||||
|
#ifndef FUZZING_HEADERS_NO_IMPL
|
||||||
|
{
|
||||||
|
if ( NullTerminated == false ) {
|
||||||
|
allocate_and_copy(data, size);
|
||||||
|
} else {
|
||||||
|
allocate_plus_1_and_copy(data, size);
|
||||||
|
_data[size] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
access_hook();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
Container(const T& t)
|
||||||
|
#ifndef FUZZING_HEADERS_NO_IMPL
|
||||||
|
{
|
||||||
|
Container(t.data(), t.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
~Container(void)
|
||||||
|
#ifndef FUZZING_HEADERS_NO_IMPL
|
||||||
|
{
|
||||||
|
this->free();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// The copy constructor was not originally explicitly supplied
|
||||||
|
// so it must have been incorrectly just copying the pointers.
|
||||||
|
Container(const Container &c) {
|
||||||
|
InvalidAddress = c.InvalidAddress;
|
||||||
|
allocate_and_copy(c._data, c._size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Container& operator=(Container &c) {
|
||||||
|
InvalidAddress = c.InvalidAddress;
|
||||||
|
allocate_and_copy(c._data, c._size);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <bool UseMSAN = false> using String = Container<char, true, UseMSAN>;
|
||||||
|
template <bool UseMSAN = false> using Data = Container<uint8_t, false, UseMSAN>;
|
||||||
|
|
||||||
|
} /* namespace types */
|
||||||
|
} /* namespace fuzzing */
|
||||||
Reference in New Issue
Block a user