xref: /aosp_15_r20/external/flac/oss-fuzz/fuzzing/datasource/datasource.hpp (revision 600f14f40d737144c998e2ec7a483122d3776fbc)
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         Base(void) = default;
44         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                 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
Get(const uint64_t id)63 template<class T> T Base::Get(const uint64_t id)
64 {
65     T ret;
66     const auto v = get(sizeof(ret), sizeof(ret), id);
67     memcpy(&ret, v.data(), sizeof(ret));
68     return ret;
69 }
70 
Get(const uint64_t id)71 template <> bool Base::Get<bool>(const uint64_t id)
72 {
73     uint8_t ret;
74     const auto v = get(sizeof(ret), sizeof(ret), id);
75     memcpy(&ret, v.data(), sizeof(ret));
76     return (ret % 2) ? true : false;
77 }
78 
Get(const uint64_t id)79 template <> std::string Base::Get<std::string>(const uint64_t id)
80 {
81     auto data = GetData(id);
82     return std::string(data.data(), data.data() + data.size());
83 }
84 
Get(const uint64_t id)85 template <> std::vector<std::string> Base::Get<std::vector<std::string>>(const uint64_t id)
86 {
87     std::vector<std::string> ret;
88     while ( true ) {
89         auto data = GetData(id);
90         ret.push_back( std::string(data.data(), data.data() + data.size()) );
91         if ( Get<bool>(id) == false ) {
92             break;
93         }
94     }
95     return ret;
96 }
97 
GetChoice(const uint64_t id)98 uint16_t Base::GetChoice(const uint64_t id)
99 {
100     return Get<uint16_t>(id);
101 }
102 
GetData(const uint64_t id,const size_t min,const size_t max)103 std::vector<uint8_t> Base::GetData(const uint64_t id, const size_t min, const size_t max)
104 {
105     return get(min, max, id);
106 }
107 
108 
Get(const uint64_t id)109 template <> types::String<> Base::Get<types::String<>>(const uint64_t id) {
110     const auto data = GetData(id);
111     types::String<> ret(data.data(), data.size());
112     return ret;
113 }
114 
Get(const uint64_t id)115 template <> types::Data<> Base::Get<types::Data<>>(const uint64_t id) {
116     const auto data = GetData(id);
117     types::Data<> ret(data.data(), data.size());
118     return ret;
119 }
120 
121 template <class T>
GetVector(const uint64_t id)122 std::vector<T> Base::GetVector(const uint64_t id) {
123     std::vector<T> ret;
124 
125     while ( Get<bool>(id) == true ) {
126         ret.push_back( Get<T>(id) );
127     }
128 
129     return ret;
130 }
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.
Datasource(const Datasource &)143         Datasource(const Datasource &) : data(0), size(0), idx(0), left(0) {}
operator =(const Datasource &)144         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
Datasource(const uint8_t * _data,const size_t _size)150 Datasource::Datasource(const uint8_t* _data, const size_t _size) :
151     Base(), data(_data), size(_size), idx(0), left(size)
152 {
153 }
154 
get(const size_t min,const size_t max,const uint64_t id)155 std::vector<uint8_t> Datasource::get(const size_t min, const size_t max, const uint64_t id) {
156     (void)id;
157 
158     uint32_t getSize;
159     if ( left < sizeof(getSize) ) {
160         throw OutOfData();
161     }
162     memcpy(&getSize, data + idx, sizeof(getSize));
163     idx += sizeof(getSize);
164     left -= sizeof(getSize);
165 
166     if ( getSize < min ) {
167         getSize = min;
168     }
169     if ( max && getSize > max ) {
170         getSize = max;
171     }
172 
173     if ( left < getSize ) {
174         throw OutOfData();
175     }
176 
177     std::vector<uint8_t> ret(getSize);
178 
179     if ( getSize > 0 ) {
180         memcpy(ret.data(), data + idx, getSize);
181     }
182     idx += getSize;
183     left -= getSize;
184 
185     return ret;
186 }
187 #endif
188 
189 } /* namespace datasource */
190 } /* namespace fuzzing */
191