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