diff --git a/immer/detail/hamts/node.hpp b/immer/detail/hamts/node.hpp index 07ecc4af..31af2105 100644 --- a/immer/detail/hamts/node.hpp +++ b/immer/detail/hamts/node.hpp @@ -615,8 +615,8 @@ struct node make_merged(shift_t shift, T v1, hash_t hash1, T v2, hash_t hash2) { if (shift < max_shift) { - const count_t idx1 = hash1 & (mask << shift); - const count_t idx2 = hash2 & (mask << shift); + auto idx1 = hash1 & (mask << shift); + auto idx2 = hash2 & (mask << shift); if (idx1 == idx2) { auto merged = make_merged( shift + B, std::move(v1), hash1, std::move(v2), hash2); diff --git a/test/oss-fuzz/data/clusterfuzz-testcase-minimized-map-st-5193157168594944 b/test/oss-fuzz/data/clusterfuzz-testcase-minimized-map-st-5193157168594944 new file mode 100644 index 00000000..2fa24ede Binary files /dev/null and b/test/oss-fuzz/data/clusterfuzz-testcase-minimized-map-st-5193157168594944 differ diff --git a/test/oss-fuzz/map-st-0.cpp b/test/oss-fuzz/map-st-0.cpp new file mode 100644 index 00000000..4435fb04 --- /dev/null +++ b/test/oss-fuzz/map-st-0.cpp @@ -0,0 +1,113 @@ +// +// 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 "input.hpp" + +#include "extra/fuzzer/fuzzer_gc_guard.hpp" + +#include +#include + +#include + +using st_memory = immer::memory_policy, + immer::unsafe_refcount_policy, + immer::no_lock_policy, + immer::no_transience_policy, + false>; + +struct colliding_hash_t +{ + std::size_t operator()(std::size_t x) const { return x & ~15; } +}; + +namespace { + +int run_input(const std::uint8_t* data, std::size_t size) +{ + constexpr auto var_count = 4; + + using map_t = immer:: + map, st_memory>; + + auto vars = std::array{}; + + auto is_valid_var = [&](auto idx) { return idx >= 0 && idx < var_count; }; + + return fuzzer_input{data, size}.run([&](auto& in) { + enum ops + { + op_set, + op_erase, + op_set_move, + op_erase_move, + op_iterate, + op_find, + op_update + }; + auto src = read(in, is_valid_var); + auto dst = read(in, is_valid_var); + switch (read(in)) { + case op_set: { + auto value = read(in); + vars[dst] = vars[src].set(value, 42); + break; + } + case op_erase: { + auto value = read(in); + vars[dst] = vars[src].erase(value); + break; + } + case op_set_move: { + auto value = read(in); + vars[dst] = std::move(vars[src]).set(value, 42); + break; + } + case op_erase_move: { + auto value = read(in); + vars[dst] = std::move(vars[src]).erase(value); + break; + } + case op_iterate: { + auto srcv = vars[src]; + for (const auto& v : srcv) { + vars[dst] = vars[dst].set(v.first, v.second); + } + break; + } + case op_find: { + auto value = read(in); + auto res = vars[src].find(value); + if (res != nullptr) { + vars[dst] = vars[dst].set(*res, 42); + } + break; + } + case op_update: { + auto key = read(in); + vars[dst] = vars[src].update(key, [](int x) { return x + 1; }); + break; + } + default: + break; + }; + return true; + }); +} + +} // namespace + +TEST_CASE("https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=24466") +{ + SECTION("fuzzer") + { + auto input = load_input( + "clusterfuzz-testcase-minimized-map-st-5193157168594944"); + CHECK(run_input(input.data(), input.size()) == 0); + } +}