1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
//
// immer: immutable data structures for C++
// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
//
// This software is distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
//
#include "fuzzer_input.hpp"
#include <immer/box.hpp>
#include <immer/flex_vector.hpp>
#include <array>
using st_memory = immer::memory_policy<immer::heap_policy<immer::cpp_heap>,
immer::unsafe_refcount_policy,
immer::no_lock_policy,
immer::no_transience_policy,
false>;
extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data,
std::size_t size)
{
constexpr auto var_count = 8;
constexpr auto bits = 3;
using vector_t = immer::flex_vector<int, st_memory, bits, bits>;
using size_t = std::uint8_t;
auto vars = std::array<vector_t, var_count>{};
auto is_valid_var = [&](auto idx) { return idx >= 0 && idx < var_count; };
auto is_valid_var_neq = [](auto other) {
return [=](auto idx) {
return idx >= 0 && idx < var_count && idx != other;
};
};
auto is_valid_index = [](auto& v) {
return [&](auto idx) { return idx >= 0 && idx < v.size(); };
};
auto is_valid_size = [](auto& v) {
return [&](auto idx) { return idx >= 0 && idx <= v.size(); };
};
auto can_concat = [](auto&& v1, auto&& v2) {
return v1.size() + v2.size() < vector_t::max_size();
};
auto can_compare = [](auto&& v) {
// avoid comparing vectors that are too big, and hence, slow to compare
return v.size() < (1 << 15);
};
return fuzzer_input{data, size}.run([&](auto& in) {
enum ops
{
op_push_back,
op_update,
op_take,
op_drop,
op_concat,
op_push_back_move,
op_update_move,
op_take_move,
op_drop_move,
op_concat_move_l,
op_concat_move_r,
op_concat_move_lr,
op_insert,
op_erase,
op_compare,
};
auto src = read<char>(in, is_valid_var);
auto dst = read<char>(in, is_valid_var);
switch (read<char>(in)) {
case op_push_back: {
vars[dst] = vars[src].push_back(42);
break;
}
case op_update: {
auto idx = read<size_t>(in, is_valid_index(vars[src]));
vars[dst] = vars[src].update(idx, [](auto x) { return x + 1; });
break;
}
case op_take: {
auto idx = read<size_t>(in, is_valid_size(vars[src]));
vars[dst] = vars[src].take(idx);
break;
}
case op_drop: {
auto idx = read<size_t>(in, is_valid_size(vars[src]));
vars[dst] = vars[src].drop(idx);
break;
}
case op_concat: {
auto src2 = read<char>(in, is_valid_var);
if (can_concat(vars[src], vars[src2]))
vars[dst] = vars[src] + vars[src2];
break;
}
case op_push_back_move: {
vars[dst] = std::move(vars[src]).push_back(21);
break;
}
case op_update_move: {
auto idx = read<size_t>(in, is_valid_index(vars[src]));
vars[dst] =
std::move(vars[src]).update(idx, [](auto x) { return x + 1; });
break;
}
case op_take_move: {
auto idx = read<size_t>(in, is_valid_size(vars[src]));
vars[dst] = std::move(vars[src]).take(idx);
break;
}
case op_drop_move: {
auto idx = read<size_t>(in, is_valid_size(vars[src]));
vars[dst] = std::move(vars[src]).drop(idx);
break;
}
case op_concat_move_l: {
auto src2 = read<char>(in, is_valid_var_neq(src));
if (can_concat(vars[src], vars[src2]))
vars[dst] = std::move(vars[src]) + vars[src2];
break;
}
case op_concat_move_r: {
auto src2 = read<char>(in, is_valid_var_neq(src));
if (can_concat(vars[src], vars[src2]))
vars[dst] = vars[src] + std::move(vars[src2]);
break;
}
case op_concat_move_lr: {
auto src2 = read<char>(in, is_valid_var_neq(src));
if (can_concat(vars[src], vars[src2]))
vars[dst] = std::move(vars[src]) + std::move(vars[src2]);
break;
}
case op_compare: {
using std::swap;
if (can_compare(vars[src]) && vars[src] == vars[dst])
swap(vars[src], vars[dst]);
break;
}
case op_erase: {
auto idx = read<size_t>(in, is_valid_index(vars[src]));
vars[dst] = vars[src].erase(idx);
break;
}
case op_insert: {
auto idx = read<size_t>(in, is_valid_size(vars[src]));
vars[dst] = vars[src].insert(idx, immer::box<int>{42});
break;
}
default:
break;
};
return true;
});
}
|