Coverage Report

Created: 2026-02-26 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/immer/extra/fuzzer/flex-vector-gc.cpp
Line
Count
Source
1
//
2
// immer: immutable data structures for C++
3
// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
4
//
5
// This software is distributed under the Boost Software License, Version 1.0.
6
// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
7
//
8
9
#include "fuzzer_input.hpp"
10
11
#include <immer/flex_vector.hpp>
12
#include <immer/flex_vector_transient.hpp>
13
#include <immer/heap/gc_heap.hpp>
14
#include <immer/refcount/no_refcount_policy.hpp>
15
16
#include <array>
17
18
using gc_memory = immer::memory_policy<immer::heap_policy<immer::gc_heap>,
19
                                       immer::no_refcount_policy,
20
                                       immer::default_lock_policy,
21
                                       immer::gc_transience_policy,
22
                                       false>;
23
24
extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data,
25
                                      std::size_t size)
26
7.62k
{
27
7.62k
    auto guard = immer::gc_disable_guard{};
28
29
7.62k
    constexpr auto var_count = 4;
30
7.62k
    constexpr auto bits      = 2;
31
32
7.62k
    using vector_t    = immer::flex_vector<int, gc_memory, bits, bits>;
33
7.62k
    using transient_t = typename vector_t::transient_type;
34
7.62k
    using size_t      = std::uint8_t;
35
36
7.62k
    auto vs = std::array<vector_t, var_count>{};
37
7.62k
    auto ts = std::array<transient_t, var_count>{};
38
39
2.83M
    auto is_valid_var = [&](auto idx) { return idx >= 0 && idx < var_count; };
40
1.76M
    auto is_valid_var_neq = [](auto other) {
41
1.81M
        return [=](auto idx) {
42
1.81M
            return idx >= 0 && idx < var_count && idx != other;
43
1.81M
        };
44
1.76M
    };
45
16.4k
    auto is_valid_index = [](auto& v) {
46
19.2k
        return [&](auto idx) { return idx >= 0 && idx < v.size(); };
flex-vector-gc.cpp:auto LLVMFuzzerTestOneInput::$_2::operator()<immer::flex_vector<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u> >(immer::flex_vector<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>&) const::{lambda(auto:1)#1}::operator()<unsigned char>(unsigned char) const
Line
Count
Source
46
6.90k
        return [&](auto idx) { return idx >= 0 && idx < v.size(); };
flex-vector-gc.cpp:auto LLVMFuzzerTestOneInput::$_2::operator()<immer::flex_vector_transient<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u> >(immer::flex_vector_transient<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>&) const::{lambda(auto:1)#1}::operator()<unsigned char>(unsigned char) const
Line
Count
Source
46
12.3k
        return [&](auto idx) { return idx >= 0 && idx < v.size(); };
47
16.4k
    };
flex-vector-gc.cpp:auto LLVMFuzzerTestOneInput::$_2::operator()<immer::flex_vector<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u> >(immer::flex_vector<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>&) const
Line
Count
Source
45
5.86k
    auto is_valid_index = [](auto& v) {
46
5.86k
        return [&](auto idx) { return idx >= 0 && idx < v.size(); };
47
5.86k
    };
flex-vector-gc.cpp:auto LLVMFuzzerTestOneInput::$_2::operator()<immer::flex_vector_transient<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u> >(immer::flex_vector_transient<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>&) const
Line
Count
Source
45
10.6k
    auto is_valid_index = [](auto& v) {
46
10.6k
        return [&](auto idx) { return idx >= 0 && idx < v.size(); };
47
10.6k
    };
48
70.8k
    auto is_valid_size = [](auto& v) {
49
86.2k
        return [&](auto idx) { return idx >= 0 && idx <= v.size(); };
flex-vector-gc.cpp:auto LLVMFuzzerTestOneInput::$_3::operator()<immer::flex_vector<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u> >(immer::flex_vector<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>&) const::{lambda(auto:1)#1}::operator()<unsigned char>(unsigned char) const
Line
Count
Source
49
46.6k
        return [&](auto idx) { return idx >= 0 && idx <= v.size(); };
flex-vector-gc.cpp:auto LLVMFuzzerTestOneInput::$_3::operator()<immer::flex_vector_transient<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u> >(immer::flex_vector_transient<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>&) const::{lambda(auto:1)#1}::operator()<unsigned char>(unsigned char) const
Line
Count
Source
49
39.6k
        return [&](auto idx) { return idx >= 0 && idx <= v.size(); };
50
70.8k
    };
flex-vector-gc.cpp:auto LLVMFuzzerTestOneInput::$_3::operator()<immer::flex_vector<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u> >(immer::flex_vector<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>&) const
Line
Count
Source
48
32.6k
    auto is_valid_size = [](auto& v) {
49
32.6k
        return [&](auto idx) { return idx >= 0 && idx <= v.size(); };
50
32.6k
    };
flex-vector-gc.cpp:auto LLVMFuzzerTestOneInput::$_3::operator()<immer::flex_vector_transient<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u> >(immer::flex_vector_transient<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>&) const
Line
Count
Source
48
38.2k
    auto is_valid_size = [](auto& v) {
49
38.2k
        return [&](auto idx) { return idx >= 0 && idx <= v.size(); };
50
38.2k
    };
51
1.82M
    auto can_concat = [](auto&& v1, auto&& v2) {
52
1.82M
        return v1.size() + v2.size() < vector_t::max_size();
53
1.82M
    };
flex-vector-gc.cpp:auto LLVMFuzzerTestOneInput::$_4::operator()<immer::flex_vector<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>&, immer::flex_vector<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>&>(immer::flex_vector<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>&, immer::flex_vector<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>&) const
Line
Count
Source
51
56.7k
    auto can_concat = [](auto&& v1, auto&& v2) {
52
56.7k
        return v1.size() + v2.size() < vector_t::max_size();
53
56.7k
    };
flex-vector-gc.cpp:auto LLVMFuzzerTestOneInput::$_4::operator()<immer::flex_vector_transient<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>&, immer::flex_vector_transient<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>&>(immer::flex_vector_transient<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>&, immer::flex_vector_transient<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false>, 2u, 2u>&) const
Line
Count
Source
51
1.76M
    auto can_concat = [](auto&& v1, auto&& v2) {
52
1.76M
        return v1.size() + v2.size() < vector_t::max_size();
53
1.76M
    };
54
55
2.21M
    return fuzzer_input{data, size}.run([&](auto& in) {
56
2.21M
        enum ops
57
2.21M
        {
58
2.21M
            op_transient,
59
2.21M
            op_persistent,
60
2.21M
            op_push_back,
61
2.21M
            op_update,
62
2.21M
            op_take,
63
2.21M
            op_drop,
64
2.21M
            op_concat,
65
2.21M
            op_push_back_mut,
66
2.21M
            op_update_mut,
67
2.21M
            op_take_mut,
68
2.21M
            op_drop_mut,
69
2.21M
            op_prepend_mut,
70
2.21M
            op_prepend_mut_move,
71
2.21M
            op_append_mut,
72
2.21M
            op_append_mut_move,
73
2.21M
        };
74
2.21M
        auto dst = read<char>(in, is_valid_var);
75
2.21M
        switch (read<char>(in)) {
76
113k
        case op_transient: {
77
113k
            auto src = read<char>(in, is_valid_var);
78
113k
            ts[dst]  = vs[src].transient();
79
113k
            break;
80
0
        }
81
19.8k
        case op_persistent: {
82
19.8k
            auto src = read<char>(in, is_valid_var);
83
19.8k
            vs[dst]  = ts[src].persistent();
84
19.8k
            break;
85
0
        }
86
75.0k
        case op_push_back: {
87
75.0k
            auto src = read<char>(in, is_valid_var);
88
75.0k
            vs[dst]  = vs[src].push_back(42);
89
75.0k
            break;
90
0
        }
91
5.90k
        case op_update: {
92
5.90k
            auto src = read<char>(in, is_valid_var);
93
5.90k
            auto idx = read<size_t>(in, is_valid_index(vs[src]));
94
5.90k
            vs[dst]  = vs[src].update(idx, [](auto x) { return x + 1; });
95
5.90k
            break;
96
0
        }
97
13.4k
        case op_take: {
98
13.4k
            auto src = read<char>(in, is_valid_var);
99
13.4k
            auto idx = read<size_t>(in, is_valid_size(vs[src]));
100
13.4k
            vs[dst]  = vs[src].take(idx);
101
13.4k
            break;
102
0
        }
103
19.2k
        case op_drop: {
104
19.2k
            auto src = read<char>(in, is_valid_var);
105
19.2k
            auto idx = read<size_t>(in, is_valid_size(vs[src]));
106
19.2k
            vs[dst]  = vs[src].drop(idx);
107
19.2k
            break;
108
0
        }
109
56.8k
        case op_concat: {
110
56.8k
            auto src  = read<char>(in, is_valid_var);
111
56.8k
            auto src2 = read<char>(in, is_valid_var);
112
56.8k
            if (can_concat(vs[src], vs[src2]))
113
55.3k
                vs[dst] = vs[src] + vs[src2];
114
56.8k
            break;
115
0
        }
116
50.5k
        case op_push_back_mut: {
117
50.5k
            ts[dst].push_back(13);
118
50.5k
            break;
119
0
        }
120
10.6k
        case op_update_mut: {
121
10.6k
            auto idx = read<size_t>(in, is_valid_index(ts[dst]));
122
10.6k
            ts[dst].update(idx, [](auto x) { return x + 1; });
123
10.6k
            break;
124
0
        }
125
38.2k
        case op_take_mut: {
126
38.2k
            auto idx = read<size_t>(in, is_valid_size(ts[dst]));
127
38.2k
            ts[dst].take(idx);
128
38.2k
            break;
129
0
        }
130
34.0k
        case op_prepend_mut: {
131
34.0k
            auto src = read<char>(in, is_valid_var_neq(dst));
132
34.0k
            if (can_concat(ts[dst], ts[src]))
133
31.7k
                ts[dst].prepend(ts[src]);
134
34.0k
            break;
135
0
        }
136
4.24k
        case op_prepend_mut_move: {
137
4.24k
            auto src = read<char>(in, is_valid_var_neq(dst));
138
4.24k
            if (can_concat(ts[dst], ts[src])) {
139
3.69k
                ts[dst].prepend(std::move(ts[src]));
140
3.69k
                ts[src] = {};
141
3.69k
            }
142
4.24k
            break;
143
0
        }
144
1.72M
        case op_append_mut: {
145
1.72M
            auto src = read<char>(in, is_valid_var_neq(dst));
146
1.72M
            if (can_concat(ts[dst], ts[src]))
147
1.69M
                ts[dst].append(ts[src]);
148
1.72M
            break;
149
0
        }
150
5.78k
        case op_append_mut_move: {
151
5.78k
            auto src = read<char>(in, is_valid_var_neq(dst));
152
5.78k
            if (can_concat(ts[dst], ts[src])) {
153
5.41k
                ts[dst].append(std::move(ts[src]));
154
5.41k
                ts[src] = {};
155
5.41k
            }
156
5.78k
            break;
157
0
        }
158
33.1k
        default:
159
33.1k
            break;
160
2.21M
        };
161
2.20M
        return true;
162
2.21M
    });
163
7.62k
}