Coverage Report

Created: 2026-06-12 16:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/bitcoin/src/test/fuzz/prevector.cpp
Line
Count
Source
1
// Copyright (c) 2015-present The Bitcoin Core developers
2
// Distributed under the MIT software license, see the accompanying
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5
#include <prevector.h>
6
#include <serialize.h>
7
#include <streams.h>
8
#include <test/fuzz/FuzzedDataProvider.h>
9
#include <test/fuzz/fuzz.h>
10
11
#include <ranges>
12
#include <vector>
13
namespace {
14
15
template <unsigned int N, typename T>
16
class prevector_tester
17
{
18
    typedef std::vector<T> realtype;
19
    realtype real_vector;
20
    realtype real_vector_alt;
21
22
    typedef prevector<N, T> pretype;
23
    pretype pre_vector;
24
    pretype pre_vector_alt;
25
26
    typedef typename pretype::size_type Size;
27
28
public:
29
    void test() const
30
0
    {
31
0
        const pretype& const_pre_vector = pre_vector;
32
0
        assert(real_vector.size() == pre_vector.size());
  Branch (32:9): [True: 0, False: 0]
33
0
        assert(real_vector.empty() == pre_vector.empty());
  Branch (33:9): [True: 0, False: 0]
34
0
        for (Size s = 0; s < real_vector.size(); s++) {
  Branch (34:26): [True: 0, False: 0]
35
0
            assert(real_vector[s] == pre_vector[s]);
  Branch (35:13): [True: 0, False: 0]
36
0
            assert(&(pre_vector[s]) == &(pre_vector.begin()[s]));
  Branch (36:13): [True: 0, False: 0]
37
0
            assert(&(pre_vector[s]) == &*(pre_vector.begin() + s));
  Branch (37:13): [True: 0, False: 0]
38
0
            assert(&(pre_vector[s]) == &*((pre_vector.end() + s) - real_vector.size()));
  Branch (38:13): [True: 0, False: 0]
39
0
        }
40
        // assert(realtype(pre_vector) == real_vector);
41
0
        assert(pretype(real_vector.begin(), real_vector.end()) == pre_vector);
  Branch (41:9): [True: 0, False: 0]
42
0
        assert(pretype(pre_vector.begin(), pre_vector.end()) == pre_vector);
  Branch (42:9): [True: 0, False: 0]
43
0
        size_t pos = 0;
44
0
        for (const T& v : pre_vector) {
  Branch (44:25): [True: 0, False: 0]
45
0
            assert(v == real_vector[pos]);
  Branch (45:13): [True: 0, False: 0]
46
0
            ++pos;
47
0
        }
48
0
        for (const T& v : pre_vector | std::views::reverse) {
  Branch (48:25): [True: 0, False: 0]
49
0
            --pos;
50
0
            assert(v == real_vector[pos]);
  Branch (50:13): [True: 0, False: 0]
51
0
        }
52
0
        for (const T& v : const_pre_vector) {
  Branch (52:25): [True: 0, False: 0]
53
0
            assert(v == real_vector[pos]);
  Branch (53:13): [True: 0, False: 0]
54
0
            ++pos;
55
0
        }
56
0
        for (const T& v : const_pre_vector | std::views::reverse) {
  Branch (56:25): [True: 0, False: 0]
57
0
            --pos;
58
0
            assert(v == real_vector[pos]);
  Branch (58:13): [True: 0, False: 0]
59
0
        }
60
0
        DataStream ss1{};
61
0
        DataStream ss2{};
62
0
        ss1 << real_vector;
63
0
        ss2 << pre_vector;
64
0
        assert(ss1.size() == ss2.size());
  Branch (64:9): [True: 0, False: 0]
65
0
        for (Size s = 0; s < ss1.size(); s++) {
  Branch (65:26): [True: 0, False: 0]
66
0
            assert(ss1[s] == ss2[s]);
  Branch (66:13): [True: 0, False: 0]
67
0
        }
68
0
    }
69
70
    void resize(Size s)
71
0
    {
72
0
        real_vector.resize(s);
73
0
        assert(real_vector.size() == s);
  Branch (73:9): [True: 0, False: 0]
74
0
        pre_vector.resize(s);
75
0
        assert(pre_vector.size() == s);
  Branch (75:9): [True: 0, False: 0]
76
0
    }
77
78
    void reserve(Size s)
79
0
    {
80
0
        real_vector.reserve(s);
81
0
        assert(real_vector.capacity() >= s);
  Branch (81:9): [True: 0, False: 0]
82
0
        pre_vector.reserve(s);
83
0
        assert(pre_vector.capacity() >= s);
  Branch (83:9): [True: 0, False: 0]
84
0
    }
85
86
    void insert(Size position, const T& value)
87
0
    {
88
0
        real_vector.insert(real_vector.begin() + position, value);
89
0
        pre_vector.insert(pre_vector.begin() + position, value);
90
0
    }
91
92
    void insert(Size position, Size count, const T& value)
93
0
    {
94
0
        real_vector.insert(real_vector.begin() + position, count, value);
95
0
        pre_vector.insert(pre_vector.begin() + position, count, value);
96
0
    }
97
98
    template <typename I>
99
    void insert_range(Size position, I first, I last)
100
0
    {
101
0
        real_vector.insert(real_vector.begin() + position, first, last);
102
0
        pre_vector.insert(pre_vector.begin() + position, first, last);
103
0
    }
104
105
    void erase(Size position)
106
0
    {
107
0
        real_vector.erase(real_vector.begin() + position);
108
0
        pre_vector.erase(pre_vector.begin() + position);
109
0
    }
110
111
    void erase(Size first, Size last)
112
0
    {
113
0
        real_vector.erase(real_vector.begin() + first, real_vector.begin() + last);
114
0
        pre_vector.erase(pre_vector.begin() + first, pre_vector.begin() + last);
115
0
    }
116
117
    void update(Size pos, const T& value)
118
0
    {
119
0
        real_vector[pos] = value;
120
0
        pre_vector[pos] = value;
121
0
    }
122
123
    void push_back(const T& value)
124
0
    {
125
0
        real_vector.push_back(value);
126
0
        pre_vector.push_back(value);
127
0
    }
128
129
    void pop_back()
130
0
    {
131
0
        real_vector.pop_back();
132
0
        pre_vector.pop_back();
133
0
    }
134
135
    void clear()
136
0
    {
137
0
        real_vector.clear();
138
0
        pre_vector.clear();
139
0
    }
140
141
    void assign(Size n, const T& value)
142
0
    {
143
0
        real_vector.assign(n, value);
144
0
        pre_vector.assign(n, value);
145
0
    }
146
147
    Size size() const
148
0
    {
149
0
        return real_vector.size();
150
0
    }
151
152
    Size capacity() const
153
    {
154
        return pre_vector.capacity();
155
    }
156
157
    void shrink_to_fit()
158
0
    {
159
0
        pre_vector.shrink_to_fit();
160
0
    }
161
162
    void swap() noexcept
163
0
    {
164
0
        real_vector.swap(real_vector_alt);
165
0
        pre_vector.swap(pre_vector_alt);
166
0
    }
167
168
    void move()
169
0
    {
170
0
        real_vector = std::move(real_vector_alt);
171
0
        real_vector_alt.clear();
172
0
        pre_vector = std::move(pre_vector_alt);
173
0
        pre_vector_alt.clear();
174
0
    }
175
176
    void copy()
177
0
    {
178
0
        real_vector = real_vector_alt;
179
0
        pre_vector = pre_vector_alt;
180
0
    }
181
182
    void resize_uninitialized(realtype values)
183
0
    {
184
0
        size_t r = values.size();
185
0
        size_t s = real_vector.size() / 2;
186
0
        if (real_vector.capacity() < s + r) {
  Branch (186:13): [True: 0, False: 0]
187
0
            real_vector.reserve(s + r);
188
0
        }
189
0
        real_vector.resize(s);
190
0
        pre_vector.resize_uninitialized(s);
191
0
        for (auto v : values) {
  Branch (191:21): [True: 0, False: 0]
192
0
            real_vector.push_back(v);
193
0
        }
194
0
        auto p = pre_vector.size();
195
0
        pre_vector.resize_uninitialized(p + r);
196
0
        for (auto v : values) {
  Branch (196:21): [True: 0, False: 0]
197
0
            pre_vector[p] = v;
198
0
            ++p;
199
0
        }
200
0
    }
201
};
202
203
} // namespace
204
205
FUZZ_TARGET(prevector)
206
0
{
207
0
    FuzzedDataProvider prov(buffer.data(), buffer.size());
208
0
    prevector_tester<8, int> test;
209
210
0
    LIMITED_WHILE(prov.remaining_bytes(), 3000)
211
0
    {
212
0
        switch (prov.ConsumeIntegralInRange<int>(0, 13 + 3 * (test.size() > 0))) {
  Branch (212:17): [True: 0, False: 0]
213
0
        case 0: {
  Branch (213:9): [True: 0, False: 0]
214
0
            auto position = prov.ConsumeIntegralInRange<size_t>(0, test.size());
215
0
            auto value = prov.ConsumeIntegral<int>();
216
0
            test.insert(position, value);
217
0
        } break;
218
0
        case 1:
  Branch (218:9): [True: 0, False: 0]
219
0
            test.resize(std::max(0, std::min(30, (int)test.size() + prov.ConsumeIntegralInRange<int>(0, 4) - 2)));
220
0
            break;
221
0
        case 2: {
  Branch (221:9): [True: 0, False: 0]
222
0
            auto position = prov.ConsumeIntegralInRange<size_t>(0, test.size());
223
0
            auto count = 1 + prov.ConsumeBool();
224
0
            auto value = prov.ConsumeIntegral<int>();
225
0
            test.insert(position, count, value);
226
0
        } break;
227
0
        case 3: {
  Branch (227:9): [True: 0, False: 0]
228
0
            int del = prov.ConsumeIntegralInRange<int>(0, test.size());
229
0
            int beg = prov.ConsumeIntegralInRange<int>(0, test.size() - del);
230
0
            test.erase(beg, beg + del);
231
0
            break;
232
0
        }
233
0
        case 4:
  Branch (233:9): [True: 0, False: 0]
234
0
            test.push_back(prov.ConsumeIntegral<int>());
235
0
            break;
236
0
        case 5: {
  Branch (236:9): [True: 0, False: 0]
237
0
            int values[4];
238
0
            int num = 1 + prov.ConsumeIntegralInRange<int>(0, 3);
239
0
            for (int k = 0; k < num; ++k) {
  Branch (239:29): [True: 0, False: 0]
240
0
                values[k] = prov.ConsumeIntegral<int>();
241
0
            }
242
0
            test.insert_range(prov.ConsumeIntegralInRange<size_t>(0, test.size()), values, values + num);
243
0
            break;
244
0
        }
245
0
        case 6: {
  Branch (245:9): [True: 0, False: 0]
246
0
            int num = 1 + prov.ConsumeIntegralInRange<int>(0, 15);
247
0
            std::vector<int> values(num);
248
0
            for (auto& v : values) {
  Branch (248:26): [True: 0, False: 0]
249
0
                v = prov.ConsumeIntegral<int>();
250
0
            }
251
0
            test.resize_uninitialized(values);
252
0
            break;
253
0
        }
254
0
        case 7:
  Branch (254:9): [True: 0, False: 0]
255
0
            test.reserve(prov.ConsumeIntegralInRange<size_t>(0, 32767));
256
0
            break;
257
0
        case 8:
  Branch (257:9): [True: 0, False: 0]
258
0
            test.shrink_to_fit();
259
0
            break;
260
0
        case 9:
  Branch (260:9): [True: 0, False: 0]
261
0
            test.clear();
262
0
            break;
263
0
        case 10: {
  Branch (263:9): [True: 0, False: 0]
264
0
            auto n = prov.ConsumeIntegralInRange<size_t>(0, 32767);
265
0
            auto value = prov.ConsumeIntegral<int>();
266
0
            test.assign(n, value);
267
0
        } break;
268
0
        case 11:
  Branch (268:9): [True: 0, False: 0]
269
0
            test.swap();
270
0
            break;
271
0
        case 12:
  Branch (271:9): [True: 0, False: 0]
272
0
            test.copy();
273
0
            break;
274
0
        case 13:
  Branch (274:9): [True: 0, False: 0]
275
0
            test.move();
276
0
            break;
277
0
        case 14: {
  Branch (277:9): [True: 0, False: 0]
278
0
            auto pos = prov.ConsumeIntegralInRange<size_t>(0, test.size() - 1);
279
0
            auto value = prov.ConsumeIntegral<int>();
280
0
            test.update(pos, value);
281
0
        } break;
282
0
        case 15:
  Branch (282:9): [True: 0, False: 0]
283
0
            test.erase(prov.ConsumeIntegralInRange<size_t>(0, test.size() - 1));
284
0
            break;
285
0
        case 16:
  Branch (285:9): [True: 0, False: 0]
286
0
            test.pop_back();
287
0
            break;
288
0
        }
289
0
    }
290
291
0
    test.test();
292
0
}