Coverage Report

Created: 2025-09-17 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/flac/oss-fuzz/fuzzing/datasource/datasource.hpp
Line
Count
Source
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
23.8k
        Base(void) = default;
44
23.8k
        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
141k
                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
24.5M
{
65
24.5M
    T ret;
66
24.5M
    const auto v = get(sizeof(ret), sizeof(ret), id);
67
24.5M
    memcpy(&ret, v.data(), sizeof(ret));
68
24.5M
    return ret;
69
24.5M
}
unsigned short fuzzing::datasource::Base::Get<unsigned short>(unsigned long)
Line
Count
Source
64
14.3k
{
65
14.3k
    T ret;
66
14.3k
    const auto v = get(sizeof(ret), sizeof(ret), id);
67
14.3k
    memcpy(&ret, v.data(), sizeof(ret));
68
14.3k
    return ret;
69
14.3k
}
unsigned char fuzzing::datasource::Base::Get<unsigned char>(unsigned long)
Line
Count
Source
64
340k
{
65
340k
    T ret;
66
340k
    const auto v = get(sizeof(ret), sizeof(ret), id);
67
340k
    memcpy(&ret, v.data(), sizeof(ret));
68
340k
    return ret;
69
340k
}
long fuzzing::datasource::Base::Get<long>(unsigned long)
Line
Count
Source
64
15.9k
{
65
15.9k
    T ret;
66
15.9k
    const auto v = get(sizeof(ret), sizeof(ret), id);
67
15.9k
    memcpy(&ret, v.data(), sizeof(ret));
68
15.9k
    return ret;
69
15.9k
}
unsigned int fuzzing::datasource::Base::Get<unsigned int>(unsigned long)
Line
Count
Source
64
79.9k
{
65
79.9k
    T ret;
66
79.9k
    const auto v = get(sizeof(ret), sizeof(ret), id);
67
79.9k
    memcpy(&ret, v.data(), sizeof(ret));
68
79.9k
    return ret;
69
79.9k
}
unsigned long fuzzing::datasource::Base::Get<unsigned long>(unsigned long)
Line
Count
Source
64
15.4k
{
65
15.4k
    T ret;
66
15.4k
    const auto v = get(sizeof(ret), sizeof(ret), id);
67
15.4k
    memcpy(&ret, v.data(), sizeof(ret));
68
15.4k
    return ret;
69
15.4k
}
int fuzzing::datasource::Base::Get<int>(unsigned long)
Line
Count
Source
64
24.1M
{
65
24.1M
    T ret;
66
24.1M
    const auto v = get(sizeof(ret), sizeof(ret), id);
67
24.1M
    memcpy(&ret, v.data(), sizeof(ret));
68
24.1M
    return ret;
69
24.1M
}
70
71
template <> bool Base::Get<bool>(const uint64_t id)
72
25.2M
{
73
25.2M
    uint8_t ret;
74
25.2M
    const auto v = get(sizeof(ret), sizeof(ret), id);
75
25.2M
    memcpy(&ret, v.data(), sizeof(ret));
76
25.2M
    return (ret % 2) ? true : false;
77
25.2M
}
78
79
template <> std::string Base::Get<std::string>(const uint64_t id)
80
9.87k
{
81
9.87k
    auto data = GetData(id);
82
9.87k
    return std::string(data.data(), data.data() + data.size());
83
9.87k
}
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
260k
{
105
260k
    return get(min, max, id);
106
260k
}
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
163k
std::vector<T> Base::GetVector(const uint64_t id) {
123
163k
    std::vector<T> ret;
124
125
24.2M
    while ( Get<bool>(id) == true ) {
126
24.1M
        ret.push_back( Get<T>(id) );
127
24.1M
    }
128
129
163k
    return ret;
130
163k
}
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
23.8k
    Base(), data(_data), size(_size), idx(0), left(size)
152
23.8k
{
153
23.8k
}
154
155
50.1M
std::vector<uint8_t> Datasource::get(const size_t min, const size_t max, const uint64_t id) {
156
50.1M
    (void)id;
157
158
50.1M
    uint32_t getSize;
159
50.1M
    if ( left < sizeof(getSize) ) {
160
88.0k
        throw OutOfData();
161
88.0k
    }
162
50.0M
    memcpy(&getSize, data + idx, sizeof(getSize));
163
50.0M
    idx += sizeof(getSize);
164
50.0M
    left -= sizeof(getSize);
165
166
50.0M
    if ( getSize < min ) {
167
51.8k
        getSize = min;
168
51.8k
    }
169
50.0M
    if ( max && getSize > max ) {
170
49.7M
        getSize = max;
171
49.7M
    }
172
173
50.0M
    if ( left < getSize ) {
174
53.6k
        throw OutOfData();
175
53.6k
    }
176
177
49.9M
    std::vector<uint8_t> ret(getSize);
178
179
49.9M
    if ( getSize > 0 ) {
180
49.8M
        memcpy(ret.data(), data + idx, getSize);
181
49.8M
    }
182
49.9M
    idx += getSize;
183
49.9M
    left -= getSize;
184
185
49.9M
    return ret;
186
50.0M
}
187
#endif
188
189
} /* namespace datasource */
190
} /* namespace fuzzing */