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.
diff --git a/oss-fuzz/fuzzing/Readme.md b/oss-fuzz/fuzzing/Readme.md
new file mode 100644
index 0000000..d2fbd68
--- /dev/null
+++ b/oss-fuzz/fuzzing/Readme.md
@@ -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.
diff --git a/oss-fuzz/fuzzing/datasource/datasource.hpp b/oss-fuzz/fuzzing/datasource/datasource.hpp
new file mode 100644
index 0000000..e0699d3
--- /dev/null
+++ b/oss-fuzz/fuzzing/datasource/datasource.hpp
@@ -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 */
diff --git a/oss-fuzz/fuzzing/datasource/id.hpp b/oss-fuzz/fuzzing/datasource/id.hpp
new file mode 100644
index 0000000..3ba38d7
--- /dev/null
+++ b/oss-fuzz/fuzzing/datasource/id.hpp
@@ -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 */
diff --git a/oss-fuzz/fuzzing/exception.hpp b/oss-fuzz/fuzzing/exception.hpp
new file mode 100644
index 0000000..55c360d
--- /dev/null
+++ b/oss-fuzz/fuzzing/exception.hpp
@@ -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 */
diff --git a/oss-fuzz/fuzzing/memory.hpp b/oss-fuzz/fuzzing/memory.hpp
new file mode 100644
index 0000000..804e23b
--- /dev/null
+++ b/oss-fuzz/fuzzing/memory.hpp
@@ -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 */
diff --git a/oss-fuzz/fuzzing/types.hpp b/oss-fuzz/fuzzing/types.hpp
new file mode 100644
index 0000000..f2b56fc
--- /dev/null
+++ b/oss-fuzz/fuzzing/types.hpp
@@ -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 */