Coverage Report

Created: 2025-07-23 06:43

/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 */