/src/flac/oss-fuzz/fuzzing/datasource/datasource.hpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright 2019 Guido Vranken |
2 | | * |
3 | | * Permission is hereby granted, free of charge, to any person obtaining |
4 | | * a copy of this software and associated documentation files (the |
5 | | * "Software"), to deal in the Software without restriction, including |
6 | | * without limitation the rights to use, copy, modify, merge, publish, |
7 | | * distribute, sublicense, and/or sell copies of the Software, and to |
8 | | * permit persons to whom the Software is furnished to do so, subject |
9 | | * to the following conditions: |
10 | | * |
11 | | * The above copyright notice and this permission notice shall be |
12 | | * included in all copies or substantial portions of the Software. |
13 | | * |
14 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
15 | | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
16 | | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
17 | | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
18 | | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
19 | | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
20 | | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
21 | | * SOFTWARE. |
22 | | */ |
23 | | |
24 | | #pragma once |
25 | | |
26 | | #include <fuzzing/exception.hpp> |
27 | | #include <fuzzing/types.hpp> |
28 | | #include <cstddef> |
29 | | #include <cstdint> |
30 | | #include <cstdlib> |
31 | | #include <cstring> |
32 | | #include <string> |
33 | | #include <vector> |
34 | | |
35 | | namespace fuzzing { |
36 | | namespace datasource { |
37 | | |
38 | | class Base |
39 | | { |
40 | | protected: |
41 | | virtual std::vector<uint8_t> get(const size_t min, const size_t max, const uint64_t id = 0) = 0; |
42 | | public: |
43 | 29.5k | Base(void) = default; |
44 | 29.5k | virtual ~Base(void) = default; |
45 | | |
46 | | template<class T> T Get(const uint64_t id = 0); |
47 | | uint16_t GetChoice(const uint64_t id = 0); |
48 | | std::vector<uint8_t> GetData(const uint64_t id, const size_t min = 0, const size_t max = 0); |
49 | | template <class T> std::vector<T> GetVector(const uint64_t id = 0); |
50 | | |
51 | | class OutOfData : public fuzzing::exception::FlowException { |
52 | | public: |
53 | 165k | OutOfData() = default; |
54 | | }; |
55 | | |
56 | | class DeserializationFailure : public fuzzing::exception::FlowException { |
57 | | public: |
58 | | DeserializationFailure() = default; |
59 | | }; |
60 | | }; |
61 | | |
62 | | #ifndef FUZZING_HEADERS_NO_IMPL |
63 | | template<class T> T Base::Get(const uint64_t id) |
64 | 28.2M | { |
65 | 28.2M | T ret; |
66 | 28.2M | const auto v = get(sizeof(ret), sizeof(ret), id); |
67 | 28.2M | memcpy(&ret, v.data(), sizeof(ret)); |
68 | 28.2M | return ret; |
69 | 28.2M | } unsigned short fuzzing::datasource::Base::Get<unsigned short>(unsigned long) Line | Count | Source | 64 | 18.4k | { | 65 | 18.4k | T ret; | 66 | 18.4k | const auto v = get(sizeof(ret), sizeof(ret), id); | 67 | 18.4k | memcpy(&ret, v.data(), sizeof(ret)); | 68 | 18.4k | return ret; | 69 | 18.4k | } |
unsigned char fuzzing::datasource::Base::Get<unsigned char>(unsigned long) Line | Count | Source | 64 | 405k | { | 65 | 405k | T ret; | 66 | 405k | const auto v = get(sizeof(ret), sizeof(ret), id); | 67 | 405k | memcpy(&ret, v.data(), sizeof(ret)); | 68 | 405k | return ret; | 69 | 405k | } |
long fuzzing::datasource::Base::Get<long>(unsigned long) Line | Count | Source | 64 | 20.3k | { | 65 | 20.3k | T ret; | 66 | 20.3k | const auto v = get(sizeof(ret), sizeof(ret), id); | 67 | 20.3k | memcpy(&ret, v.data(), sizeof(ret)); | 68 | 20.3k | return ret; | 69 | 20.3k | } |
unsigned int fuzzing::datasource::Base::Get<unsigned int>(unsigned long) Line | Count | Source | 64 | 102k | { | 65 | 102k | T ret; | 66 | 102k | const auto v = get(sizeof(ret), sizeof(ret), id); | 67 | 102k | memcpy(&ret, v.data(), sizeof(ret)); | 68 | 102k | return ret; | 69 | 102k | } |
unsigned long fuzzing::datasource::Base::Get<unsigned long>(unsigned long) Line | Count | Source | 64 | 19.9k | { | 65 | 19.9k | T ret; | 66 | 19.9k | const auto v = get(sizeof(ret), sizeof(ret), id); | 67 | 19.9k | memcpy(&ret, v.data(), sizeof(ret)); | 68 | 19.9k | return ret; | 69 | 19.9k | } |
int fuzzing::datasource::Base::Get<int>(unsigned long) Line | Count | Source | 64 | 27.6M | { | 65 | 27.6M | T ret; | 66 | 27.6M | const auto v = get(sizeof(ret), sizeof(ret), id); | 67 | 27.6M | memcpy(&ret, v.data(), sizeof(ret)); | 68 | 27.6M | return ret; | 69 | 27.6M | } |
|
70 | | |
71 | | template <> bool Base::Get<bool>(const uint64_t id) |
72 | 29.0M | { |
73 | 29.0M | uint8_t ret; |
74 | 29.0M | const auto v = get(sizeof(ret), sizeof(ret), id); |
75 | 29.0M | memcpy(&ret, v.data(), sizeof(ret)); |
76 | 29.0M | return (ret % 2) ? true : false; |
77 | 29.0M | } |
78 | | |
79 | | template <> std::string Base::Get<std::string>(const uint64_t id) |
80 | 12.1k | { |
81 | 12.1k | auto data = GetData(id); |
82 | 12.1k | return std::string(data.data(), data.data() + data.size()); |
83 | 12.1k | } |
84 | | |
85 | | template <> std::vector<std::string> Base::Get<std::vector<std::string>>(const uint64_t id) |
86 | 0 | { |
87 | 0 | std::vector<std::string> ret; |
88 | 0 | while ( true ) { |
89 | 0 | auto data = GetData(id); |
90 | 0 | ret.push_back( std::string(data.data(), data.data() + data.size()) ); |
91 | 0 | if ( Get<bool>(id) == false ) { |
92 | 0 | break; |
93 | 0 | } |
94 | 0 | } |
95 | 0 | return ret; |
96 | 0 | } |
97 | | |
98 | | uint16_t Base::GetChoice(const uint64_t id) |
99 | 0 | { |
100 | 0 | return Get<uint16_t>(id); |
101 | 0 | } |
102 | | |
103 | | std::vector<uint8_t> Base::GetData(const uint64_t id, const size_t min, const size_t max) |
104 | 211k | { |
105 | 211k | return get(min, max, id); |
106 | 211k | } |
107 | | |
108 | | |
109 | 0 | template <> types::String<> Base::Get<types::String<>>(const uint64_t id) { |
110 | 0 | const auto data = GetData(id); |
111 | 0 | types::String<> ret(data.data(), data.size()); |
112 | 0 | return ret; |
113 | 0 | } |
114 | | |
115 | 0 | template <> types::Data<> Base::Get<types::Data<>>(const uint64_t id) { |
116 | 0 | const auto data = GetData(id); |
117 | 0 | types::Data<> ret(data.data(), data.size()); |
118 | 0 | return ret; |
119 | 0 | } |
120 | | |
121 | | template <class T> |
122 | 190k | std::vector<T> Base::GetVector(const uint64_t id) { |
123 | 190k | std::vector<T> ret; |
124 | | |
125 | 27.8M | while ( Get<bool>(id) == true ) { |
126 | 27.6M | ret.push_back( Get<T>(id) ); |
127 | 27.6M | } |
128 | | |
129 | 190k | return ret; |
130 | 190k | } |
131 | | #endif |
132 | | |
133 | | class Datasource : public Base |
134 | | { |
135 | | private: |
136 | | const uint8_t* data; |
137 | | const size_t size; |
138 | | size_t idx; |
139 | | size_t left; |
140 | | std::vector<uint8_t> get(const size_t min, const size_t max, const uint64_t id = 0) override; |
141 | | |
142 | | // Make copy constructor and assignment operator private. |
143 | 0 | Datasource(const Datasource &) : data(0), size(0), idx(0), left(0) {} |
144 | 0 | Datasource& operator=(const Datasource &) { return *this; } |
145 | | public: |
146 | | Datasource(const uint8_t* _data, const size_t _size); |
147 | | }; |
148 | | |
149 | | #ifndef FUZZING_HEADERS_NO_IMPL |
150 | | Datasource::Datasource(const uint8_t* _data, const size_t _size) : |
151 | 29.5k | Base(), data(_data), size(_size), idx(0), left(size) |
152 | 29.5k | { |
153 | 29.5k | } |
154 | | |
155 | 57.4M | std::vector<uint8_t> Datasource::get(const size_t min, const size_t max, const uint64_t id) { |
156 | 57.4M | (void)id; |
157 | | |
158 | 57.4M | uint32_t getSize; |
159 | 57.4M | if ( left < sizeof(getSize) ) { |
160 | 103k | throw OutOfData(); |
161 | 103k | } |
162 | 57.3M | memcpy(&getSize, data + idx, sizeof(getSize)); |
163 | 57.3M | idx += sizeof(getSize); |
164 | 57.3M | left -= sizeof(getSize); |
165 | | |
166 | 57.3M | if ( getSize < min ) { |
167 | 67.5k | getSize = min; |
168 | 67.5k | } |
169 | 57.3M | if ( max && getSize > max ) { |
170 | 57.1M | getSize = max; |
171 | 57.1M | } |
172 | | |
173 | 57.3M | if ( left < getSize ) { |
174 | 61.8k | throw OutOfData(); |
175 | 61.8k | } |
176 | | |
177 | 57.3M | std::vector<uint8_t> ret(getSize); |
178 | | |
179 | 57.3M | if ( getSize > 0 ) { |
180 | 57.2M | memcpy(ret.data(), data + idx, getSize); |
181 | 57.2M | } |
182 | 57.3M | idx += getSize; |
183 | 57.3M | left -= getSize; |
184 | | |
185 | 57.3M | return ret; |
186 | 57.3M | } |
187 | | #endif |
188 | | |
189 | | } /* namespace datasource */ |
190 | | } /* namespace fuzzing */ |