-
-
Notifications
You must be signed in to change notification settings - Fork 186
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
57a8c5e
commit 80fd4b3
Showing
50 changed files
with
8,359 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,41 @@ | ||
add_custom_target(fuzzers COMMENT "Build all fuzzers.") | ||
|
||
add_custom_target(fuzzers | ||
COMMENT "Build all fuzzers.") | ||
|
||
if (CHECK_FUZZERS) | ||
if(CHECK_FUZZERS) | ||
add_dependencies(tests fuzzers) | ||
endif() | ||
|
||
# LIB_FUZZING_ENGINE is set by the Google OSS-Fuzz | ||
# infrastructure. Otherwise we use Clang's LibFuzzer | ||
if (DEFINED ENV{LIB_FUZZING_ENGINE}) | ||
# LIB_FUZZING_ENGINE is set by the Google OSS-Fuzz infrastructure. Otherwise we | ||
# use Clang's LibFuzzer | ||
if(DEFINED ENV{LIB_FUZZING_ENGINE}) | ||
set(immer_fuzzing_engine $ENV{LIB_FUZZING_ENGINE}) | ||
else() | ||
set(immer_fuzzing_engine "-fsanitize=fuzzer") | ||
endif() | ||
|
||
file(GLOB_RECURSE immer_fuzzers "*.cpp") | ||
foreach(TMP_PATH ${immer_fuzzers}) | ||
string(FIND ${TMP_PATH} immer-archive EXCLUDE_DIR_FOUND) | ||
if(NOT ${EXCLUDE_DIR_FOUND} EQUAL -1) | ||
list(REMOVE_ITEM immer_fuzzers ${TMP_PATH}) | ||
endif() | ||
endforeach(TMP_PATH) | ||
|
||
foreach(_file IN LISTS immer_fuzzers) | ||
immer_target_name_for(_target _output "${_file}") | ||
add_executable(${_target} EXCLUDE_FROM_ALL "${_file}") | ||
set_target_properties(${_target} PROPERTIES OUTPUT_NAME ${_output}) | ||
target_compile_options(${_target} PUBLIC ${immer_fuzzing_engine}) | ||
target_link_libraries(${_target} PUBLIC ${immer_fuzzing_engine} | ||
immer-dev) | ||
target_compile_definitions(${_target} PUBLIC IMMER_THROW_ON_INVALID_STATE=1) | ||
target_link_libraries(${_target} PUBLIC ${immer_fuzzing_engine} immer-dev) | ||
add_dependencies(fuzzers ${_target}) | ||
if (CHECK_FUZZERS) | ||
if(CHECK_FUZZERS) | ||
add_test("fuzzer/${_output}" ${_output} -max_total_time=1) | ||
endif() | ||
if (immer_INSTALL_FUZZERS) | ||
if(immer_INSTALL_FUZZERS) | ||
install(TARGETS ${_target} DESTINATION bin) | ||
endif() | ||
endforeach() | ||
|
||
if(immer_BUILD_ARCHIVE_TESTS) | ||
add_subdirectory(immer-archive) | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
find_package(spdlog REQUIRED) | ||
|
||
file(GLOB_RECURSE immer_fuzzers "*.cpp") | ||
foreach(_file IN LISTS immer_fuzzers) | ||
immer_target_name_for(_target _output "${_file}") | ||
add_executable(${_target} EXCLUDE_FROM_ALL "${_file}") | ||
set_target_properties(${_target} PROPERTIES OUTPUT_NAME ${_output}) | ||
target_compile_options(${_target} PUBLIC ${immer_fuzzing_engine}) | ||
target_include_directories(${_target} PRIVATE ../..) | ||
target_link_libraries(${_target} PUBLIC ${immer_fuzzing_engine} immer-dev | ||
spdlog::spdlog) | ||
add_dependencies(fuzzers ${_target}) | ||
if(CHECK_FUZZERS) | ||
add_test("fuzzer/${_output}" ${_output} -max_total_time=1) | ||
endif() | ||
if(immer_INSTALL_FUZZERS) | ||
install(TARGETS ${_target} DESTINATION bin) | ||
endif() | ||
endforeach() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
// | ||
// 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/fuzzer_input.hpp> | ||
|
||
#include <immer/box.hpp> | ||
#include <immer/flex_vector.hpp> | ||
|
||
#include <fmt/ranges.h> | ||
#include <immer/experimental/immer-archive/rbts/load.hpp> | ||
#include <immer/experimental/immer-archive/rbts/save.hpp> | ||
|
||
#include <array> | ||
|
||
namespace { | ||
void require_eq(const auto& a, const auto& b) | ||
{ | ||
if (a != b) { | ||
throw std::runtime_error{ | ||
fmt::format("{} != {}", fmt::join(a, ", "), fmt::join(b, ", "))}; | ||
} | ||
} | ||
} // namespace | ||
|
||
extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data, | ||
std::size_t size) | ||
{ | ||
constexpr auto var_count = 8; | ||
constexpr auto bits = 2; | ||
|
||
using vector_t = | ||
immer::flex_vector<int, immer::default_memory_policy, bits, bits>; | ||
using size_t = std::uint8_t; | ||
|
||
const auto check_save_and_load = [&](const auto& vec) { | ||
auto ar = immer_archive::rbts::make_save_archive_for(vec); | ||
auto vector_id = immer_archive::container_id{}; | ||
std::tie(ar, vector_id) = immer_archive::rbts::save_to_archive(vec, ar); | ||
|
||
auto loader = | ||
immer_archive::rbts::make_loader_for(vec, fix_leaf_nodes(ar)); | ||
auto loaded = loader.load(vector_id); | ||
require_eq(vec, loaded); | ||
}; | ||
|
||
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() / 4; | ||
}; | ||
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); | ||
const auto op = read<char>(in); | ||
SPDLOG_DEBUG("op = {}", static_cast<int>(op)); | ||
switch (op) { | ||
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; | ||
}; | ||
|
||
check_save_and_load(vars[src]); | ||
check_save_and_load(vars[dst]); | ||
|
||
return true; | ||
}); | ||
} |
Oops, something went wrong.