1 #pragma once
2
3 #include <fuzzing/exception.hpp>
4 #include <fuzzing/types.hpp>
5 #include <cstddef>
6 #include <cstdint>
7 #include <cstdlib>
8 #include <cstring>
9 #include <string>
10 #include <vector>
11
12 namespace fuzzing {
13 namespace datasource {
14
15 class Base
16 {
17 protected:
18 virtual std::vector<uint8_t> get(const size_t min, const size_t max, const uint64_t id = 0) = 0;
19 public:
20 Base(void) = default;
21 virtual ~Base(void) = default;
22
23 template<class T> T Get(const uint64_t id = 0);
24 uint16_t GetChoice(const uint64_t id = 0);
25 std::vector<uint8_t> GetData(const uint64_t id, const size_t min = 0, const size_t max = 0);
26 template <class T> std::vector<T> GetVector(const uint64_t id = 0);
27
28 class OutOfData : public fuzzing::exception::FlowException {
29 public:
30 OutOfData() = default;
31 };
32
33 class DeserializationFailure : public fuzzing::exception::FlowException {
34 public:
35 DeserializationFailure() = default;
36 };
37 };
38
39 #ifndef FUZZING_HEADERS_NO_IMPL
Get(const uint64_t id)40 template<class T> T Base::Get(const uint64_t id)
41 {
42 T ret;
43 const auto v = get(sizeof(ret), sizeof(ret), id);
44 memcpy(&ret, v.data(), sizeof(ret));
45 return ret;
46 }
47
Get(const uint64_t id)48 template <> bool Base::Get<bool>(const uint64_t id)
49 {
50 uint8_t ret;
51 const auto v = get(sizeof(ret), sizeof(ret), id);
52 memcpy(&ret, v.data(), sizeof(ret));
53 return (ret % 2) ? true : false;
54 }
55
Get(const uint64_t id)56 template <> std::string Base::Get<std::string>(const uint64_t id)
57 {
58 auto data = GetData(id);
59 return std::string(data.data(), data.data() + data.size());
60 }
61
Get(const uint64_t id)62 template <> std::vector<std::string> Base::Get<std::vector<std::string>>(const uint64_t id)
63 {
64 std::vector<std::string> ret;
65 while ( true ) {
66 auto data = GetData(id);
67 ret.push_back( std::string(data.data(), data.data() + data.size()) );
68 if ( Get<bool>(id) == false ) {
69 break;
70 }
71 }
72 return ret;
73 }
74
GetChoice(const uint64_t id)75 uint16_t Base::GetChoice(const uint64_t id)
76 {
77 return Get<uint16_t>(id);
78 }
79
GetData(const uint64_t id,const size_t min,const size_t max)80 std::vector<uint8_t> Base::GetData(const uint64_t id, const size_t min, const size_t max)
81 {
82 return get(min, max, id);
83 }
84
85
Get(const uint64_t id)86 template <> types::String<> Base::Get<types::String<>>(const uint64_t id) {
87 const auto data = GetData(id);
88 types::String<> ret(data.data(), data.size());
89 return ret;
90 }
91
Get(const uint64_t id)92 template <> types::Data<> Base::Get<types::Data<>>(const uint64_t id) {
93 const auto data = GetData(id);
94 types::Data<> ret(data.data(), data.size());
95 return ret;
96 }
97
98 template <class T>
GetVector(const uint64_t id)99 std::vector<T> Base::GetVector(const uint64_t id) {
100 std::vector<T> ret;
101
102 while ( Get<bool>(id) == true ) {
103 ret.push_back( Get<T>(id) );
104 }
105
106 return ret;
107 }
108 #endif
109
110 class Datasource : public Base
111 {
112 private:
113 const uint8_t* data;
114 const size_t size;
115 size_t idx;
116 size_t left;
117 std::vector<uint8_t> get(const size_t min, const size_t max, const uint64_t id = 0) override;
118
119 // Make copy constructor and assignment operator private.
Datasource(const Datasource &)120 Datasource(const Datasource &) : data(0), size(0), idx(0), left(0) {}
operator =(const Datasource &)121 Datasource& operator=(const Datasource &) { return *this; }
122 public:
123 Datasource(const uint8_t* _data, const size_t _size);
124 };
125
126 #ifndef FUZZING_HEADERS_NO_IMPL
Datasource(const uint8_t * _data,const size_t _size)127 Datasource::Datasource(const uint8_t* _data, const size_t _size) :
128 Base(), data(_data), size(_size), idx(0), left(size)
129 {
130 }
131
get(const size_t min,const size_t max,const uint64_t id)132 std::vector<uint8_t> Datasource::get(const size_t min, const size_t max, const uint64_t id) {
133 (void)id;
134
135 uint32_t getSize;
136 if ( left < sizeof(getSize) ) {
137 throw OutOfData();
138 }
139 memcpy(&getSize, data + idx, sizeof(getSize));
140 idx += sizeof(getSize);
141 left -= sizeof(getSize);
142
143 if ( getSize < min ) {
144 getSize = min;
145 }
146 if ( max && getSize > max ) {
147 getSize = max;
148 }
149
150 if ( left < getSize ) {
151 throw OutOfData();
152 }
153
154 std::vector<uint8_t> ret(getSize);
155
156 if ( getSize > 0 ) {
157 memcpy(ret.data(), data + idx, getSize);
158 }
159 idx += getSize;
160 left -= getSize;
161
162 return ret;
163 }
164 #endif
165
166 } /* namespace datasource */
167 } /* namespace fuzzing */
168