/* Copyright 2019 Guido Vranken * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject * to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #pragma once #include #include #include #include #include #include #include #include namespace fuzzing { namespace datasource { class Base { protected: virtual std::vector get(const size_t min, const size_t max, const uint64_t id = 0) = 0; public: Base(void) = default; virtual ~Base(void) = default; template T Get(const uint64_t id = 0); uint16_t GetChoice(const uint64_t id = 0); std::vector GetData(const uint64_t id, const size_t min = 0, const size_t max = 0); template std::vector 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 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(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(const uint64_t id) { auto data = GetData(id); return std::string(data.data(), data.data() + data.size()); } template <> std::vector Base::Get>(const uint64_t id) { std::vector ret; while ( true ) { auto data = GetData(id); ret.push_back( std::string(data.data(), data.data() + data.size()) ); if ( Get(id) == false ) { break; } } return ret; } uint16_t Base::GetChoice(const uint64_t id) { return Get(id); } std::vector Base::GetData(const uint64_t id, const size_t min, const size_t max) { return get(min, max, id); } template <> types::String<> Base::Get>(const uint64_t id) { const auto data = GetData(id); types::String<> ret(data.data(), data.size()); return ret; } template <> types::Data<> Base::Get>(const uint64_t id) { const auto data = GetData(id); types::Data<> ret(data.data(), data.size()); return ret; } template std::vector Base::GetVector(const uint64_t id) { std::vector ret; while ( Get(id) == true ) { ret.push_back( Get(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 get(const size_t min, const size_t max, const uint64_t id = 0) override; // Make copy constructor and assignment operator 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 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 ret(getSize); if ( getSize > 0 ) { memcpy(ret.data(), data + idx, getSize); } idx += getSize; left -= getSize; return ret; } #endif } /* namespace datasource */ } /* namespace fuzzing */