You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
4.1 KiB
168 lines
4.1 KiB
#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 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<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 */
|