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#include <immer/vector.hpp>
11#include <immer/vector_transient.hpp>
12#include <immer/heap/gc_heap.hpp>
13#include <immer/refcount/no_refcount_policy.hpp>
14#include <iostream>
15#include <array>
16
17using gc_memory = immer::memory_policy<
18 immer::heap_policy<immer::gc_heap>,
19 immer::no_refcount_policy,
20 immer::gc_transience_policy,
21 false>;
22
23extern "C"
24int LLVMFuzzerTestOneInput(const std::uint8_t* data, std::size_t size)
25{
26 constexpr auto var_count = 4;
27 constexpr auto bits = 2;
28
29 using vector_t = immer::vector<int, gc_memory, bits, bits>;
30 using transient_t = typename vector_t::transient_type;
31 using size_t = std::uint8_t;
32
33 auto vs = std::array<vector_t, var_count>{};
34 auto ts = std::array<transient_t, var_count>{};
35
36 auto is_valid_var = [&] (auto idx) {
37 return idx >= 0 && idx < var_count;
38 };
39 auto is_valid_index = [] (auto& v) {
40 return [&] (auto idx) { return idx >= 0 && idx < v.size(); };
41 };
42 auto is_valid_size = [] (auto& v) {
43 return [&] (auto idx) { return idx >= 0 && idx <= v.size(); };
44 };
45
46 return fuzzer_input{data, size}.run([&] (auto& in)
47 {
48 enum ops {
49 op_transient,
50 op_persistent,
51 op_push_back,
52 op_update,
53 op_take,
54 op_push_back_mut,
55 op_update_mut,
56 op_take_mut,
57 };
58 auto dst = read<char>(in, is_valid_var);
59 switch (read<char>(in))
60 {
61 case op_transient: {
62 auto src = read<char>(in, is_valid_var);
63 ts[dst] = vs[src].transient();
64 break;
65 }
66 case op_persistent: {
67 auto src = read<char>(in, is_valid_var);
68 vs[dst] = ts[src].persistent();
69 break;
70 }
71 case op_push_back: {
72 auto src = read<char>(in, is_valid_var);
73 vs[dst] = vs[src].push_back(42);
74 break;
75 }
76 case op_update: {
77 auto src = read<char>(in, is_valid_var);
78 auto idx = read<size_t>(in, is_valid_index(vs[src]));
79 vs[dst] = vs[src].update(idx, [] (auto x) { return x + 1; });
80 break;
81 }
82 case op_take: {
83 auto src = read<char>(in, is_valid_var);
84 auto idx = read<size_t>(in, is_valid_size(vs[src]));
85 vs[dst] = vs[src].take(idx);
86 break;
87 }
88 case op_push_back_mut: {
89 ts[dst].push_back(13);
90 break;
91 }
92 case op_update_mut: {
93 auto idx = read<size_t>(in, is_valid_index(ts[dst]));
94 ts[dst].update(idx, [] (auto x) { return x + 1; });
95 break;
96 }
97 case op_take_mut: {
98 auto idx = read<size_t>(in, is_valid_size(ts[dst]));
99 ts[dst].take(idx);
100 break;
101 }
102 default:
103 break;
104 };
105 return true;
106 });
107}
108