Coverage Report

Created: 2026-01-17 06:28

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.73k
{
27
7.73k
    auto guard = immer::gc_disable_guard{};
28
29
7.73k
    constexpr auto var_count = 4;
30
7.73k
    constexpr auto bits      = 2;
31
32
7.73k
    using vector_t    = immer::flex_vector<int, gc_memory, bits, bits>;
33
7.73k
    using transient_t = typename vector_t::transient_type;
34
7.73k
    using size_t      = std::uint8_t;
35
36
7.73k
    auto vs = std::array<vector_t, var_count>{};
37
7.73k
    auto ts = std::array<transient_t, var_count>{};
38
39
2.85M
    auto is_valid_var = [&](auto idx) { return idx >= 0 && idx < var_count; };
40
1.81M
    auto is_valid_var_neq = [](auto other) {
41
1.86M
        return [=](auto idx) {
42
1.86M
            return idx >= 0 && idx < var_count && idx != other;
43
1.86M
        };
44
1.81M
    };
45
16.9k
    auto is_valid_index = [](auto& v) {
46
19.1k
        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.38k
        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.7k
        return [&](auto idx) { return idx >= 0 && idx < v.size(); };
47
16.9k
    };
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.61k
    auto is_valid_index = [](auto& v) {
46
5.61k
        return [&](auto idx) { return idx >= 0 && idx < v.size(); };
47
5.61k
    };
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
11.3k
    auto is_valid_index = [](auto& v) {
46
11.3k
        return [&](auto idx) { return idx >= 0 && idx < v.size(); };
47
11.3k
    };
48
67.5k
    auto is_valid_size = [](auto& v) {
49
80.9k
        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
41.4k
        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.5k
        return [&](auto idx) { return idx >= 0 && idx <= v.size(); };
50
67.5k
    };
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
29.5k
    auto is_valid_size = [](auto& v) {
49
29.5k
        return [&](auto idx) { return idx >= 0 && idx <= v.size(); };
50
29.5k
    };
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.0k
    auto is_valid_size = [](auto& v) {
49
38.0k
        return [&](auto idx) { return idx >= 0 && idx <= v.size(); };
50
38.0k
    };
51
1.87M
    auto can_concat = [](auto&& v1, auto&& v2) {
52
1.87M
        return v1.size() + v2.size() < vector_t::max_size();
53
1.87M
    };
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
57.1k
    auto can_concat = [](auto&& v1, auto&& v2) {
52
57.1k
        return v1.size() + v2.size() < vector_t::max_size();
53
57.1k
    };
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.81M
    auto can_concat = [](auto&& v1, auto&& v2) {
52
1.81M
        return v1.size() + v2.size() < vector_t::max_size();
53
1.81M
    };
54
55
2.24M
    return fuzzer_input{data, size}.run([&](auto& in) {
56
2.24M
        enum ops
57
2.24M
        {
58
2.24M
            op_transient,
59
2.24M
            op_persistent,
60
2.24M
            op_push_back,
61
2.24M
            op_update,
62
2.24M
            op_take,
63
2.24M
            op_drop,
64
2.24M
            op_concat,
65
2.24M
            op_push_back_mut,
66
2.24M
            op_update_mut,
67
2.24M
            op_take_mut,
68
2.24M
            op_drop_mut,
69
2.24M
            op_prepend_mut,
70
2.24M
            op_prepend_mut_move,
71
2.24M
            op_append_mut,
72
2.24M
            op_append_mut_move,
73
2.24M
        };
74
2.24M
        auto dst = read<char>(in, is_valid_var);
75
2.24M
        switch (read<char>(in)) {
76
111k
        case op_transient: {
77
111k
            auto src = read<char>(in, is_valid_var);
78
111k
            ts[dst]  = vs[src].transient();
79
111k
            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
73.0k
        case op_push_back: {
87
73.0k
            auto src = read<char>(in, is_valid_var);
88
73.0k
            vs[dst]  = vs[src].push_back(42);
89
73.0k
            break;
90
0
        }
91
5.65k
        case op_update: {
92
5.65k
            auto src = read<char>(in, is_valid_var);
93
5.65k
            auto idx = read<size_t>(in, is_valid_index(vs[src]));
94
5.65k
            vs[dst]  = vs[src].update(idx, [](auto x) { return x + 1; });
95
5.65k
            break;
96
0
        }
97
11.5k
        case op_take: {
98
11.5k
            auto src = read<char>(in, is_valid_var);
99
11.5k
            auto idx = read<size_t>(in, is_valid_size(vs[src]));
100
11.5k
            vs[dst]  = vs[src].take(idx);
101
11.5k
            break;
102
0
        }
103
18.0k
        case op_drop: {
104
18.0k
            auto src = read<char>(in, is_valid_var);
105
18.0k
            auto idx = read<size_t>(in, is_valid_size(vs[src]));
106
18.0k
            vs[dst]  = vs[src].drop(idx);
107
18.0k
            break;
108
0
        }
109
57.2k
        case op_concat: {
110
57.2k
            auto src  = read<char>(in, is_valid_var);
111
57.2k
            auto src2 = read<char>(in, is_valid_var);
112
57.2k
            if (can_concat(vs[src], vs[src2]))
113
55.6k
                vs[dst] = vs[src] + vs[src2];
114
57.2k
            break;
115
0
        }
116
48.6k
        case op_push_back_mut: {
117
48.6k
            ts[dst].push_back(13);
118
48.6k
            break;
119
0
        }
120
11.3k
        case op_update_mut: {
121
11.3k
            auto idx = read<size_t>(in, is_valid_index(ts[dst]));
122
11.3k
            ts[dst].update(idx, [](auto x) { return x + 1; });
123
11.3k
            break;
124
0
        }
125
38.0k
        case op_take_mut: {
126
38.0k
            auto idx = read<size_t>(in, is_valid_size(ts[dst]));
127
38.0k
            ts[dst].take(idx);
128
38.0k
            break;
129
0
        }
130
34.8k
        case op_prepend_mut: {
131
34.8k
            auto src = read<char>(in, is_valid_var_neq(dst));
132
34.8k
            if (can_concat(ts[dst], ts[src]))
133
32.3k
                ts[dst].prepend(ts[src]);
134
34.8k
            break;
135
0
        }
136
4.14k
        case op_prepend_mut_move: {
137
4.14k
            auto src = read<char>(in, is_valid_var_neq(dst));
138
4.14k
            if (can_concat(ts[dst], ts[src])) {
139
3.58k
                ts[dst].prepend(std::move(ts[src]));
140
3.58k
                ts[src] = {};
141
3.58k
            }
142
4.14k
            break;
143
0
        }
144
1.77M
        case op_append_mut: {
145
1.77M
            auto src = read<char>(in, is_valid_var_neq(dst));
146
1.77M
            if (can_concat(ts[dst], ts[src]))
147
1.74M
                ts[dst].append(ts[src]);
148
1.77M
            break;
149
0
        }
150
5.68k
        case op_append_mut_move: {
151
5.68k
            auto src = read<char>(in, is_valid_var_neq(dst));
152
5.68k
            if (can_concat(ts[dst], ts[src])) {
153
5.30k
                ts[dst].append(std::move(ts[src]));
154
5.30k
                ts[src] = {};
155
5.30k
            }
156
5.68k
            break;
157
0
        }
158
31.1k
        default:
159
31.1k
            break;
160
2.24M
        };
161
2.24M
        return true;
162
2.24M
    });
163
7.73k
}