From 3123d0df62854f57200dbadfecc3548fe550e167 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 25 Mar 2026 05:07:50 +0800 Subject: [PATCH 1/3] Add fuzz code for append_range and prepend_range --- .../deque/fuzz_deque_append.cc | 115 +++++++++++++++ include/fast_io_dsal/impl/deque.h | 139 +++++++++++------- 2 files changed, 203 insertions(+), 51 deletions(-) create mode 100644 fuzzing/0007.containers/deque/fuzz_deque_append.cc diff --git a/fuzzing/0007.containers/deque/fuzz_deque_append.cc b/fuzzing/0007.containers/deque/fuzz_deque_append.cc new file mode 100644 index 00000000..d3888d33 --- /dev/null +++ b/fuzzing/0007.containers/deque/fuzz_deque_append.cc @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(uint8_t const *data, size_t size) +{ + ::fast_io::deque dq; + std::deque ref; + + for (size_t i{}; i != size; ++i) + { + uint8_t b = data[i]; + + uint8_t op = b & 0x7u; // now 8 operations (0–7) + std::size_t len = (b >> 3) & 0x7u; // insert 0–7 elements + + // Always valid position: [0, size] + std::size_t pos = dq.size() == 0 ? 0 : (static_cast(b) * 37u) % (dq.size() + 1); + + // Build deterministic range + std::vector rg; + rg.reserve(len); + for (std::size_t j{}; j < len; ++j) + { + rg.push_back(i * 1315423911ull + j); + } + + switch (op) + { + case 0: // insert_range_index + { + dq.insert_range_index(pos, rg); + ref.insert(ref.begin() + pos, rg.begin(), rg.end()); + break; + } + + case 1: // insert_range using iterator + { + auto it = dq.insert_range(dq.cbegin() + pos, rg); + (void)it; + ref.insert(ref.begin() + pos, rg.begin(), rg.end()); + break; + } + + case 2: // erase single element + { + if (!ref.empty()) + { + std::size_t p = pos % ref.size(); + dq.erase_index(p); + ref.erase(ref.begin() + p); + } + break; + } + + case 3: // erase small range + { + if (!ref.empty()) + { + std::size_t p = pos % ref.size(); + std::size_t rlen = len % (ref.size() - p); + dq.erase_index(p, p + rlen); + ref.erase(ref.begin() + p, ref.begin() + p + rlen); + } + break; + } + + case 4: // append_range + { + dq.append_range(rg); + ref.insert(ref.end(), rg.begin(), rg.end()); + break; + } + + case 5: // prepend_range + { + dq.prepend_range(rg); + ref.insert(ref.begin(), rg.begin(), rg.end()); + break; + } + + case 6: // push_back single (optional extra fuzz) + { + dq.push_back(i); + ref.push_back(i); + break; + } + + case 7: // push_front single (optional extra fuzz) + { + dq.push_front(i); + ref.push_front(i); + break; + } + } + + // Validate correctness + if (dq.size() != ref.size()) + { + __builtin_trap(); + } + + if (!std::ranges::equal(dq, ref)) + { + __builtin_trap(); + } + } + + return 0; +} diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index 1ced898e..52f5f2c5 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -2363,6 +2363,44 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE size_type pos; iterator it; }; + template <::std::ranges::range R> + requires ::std::constructible_from> + inline constexpr insert_range_result insert_range_front_impl(size_type pos, R &&rg, size_type old_size, size_type rgsize) noexcept(::std::is_nothrow_constructible_v>) + { + ::fast_io::containers::details::deque_reserve_front_spaces(this->controller, rgsize); + auto thisbg{this->begin()}; + auto posit{thisbg + pos}; + auto thisbgrgsize{thisbg - rgsize}; + auto thisbgrgsizenew{::fast_io::freestanding::uninitialized_relocate(thisbg, + posit, thisbgrgsize)}; + ::fast_io::freestanding::uninitialized_copy_n(::std::ranges::cbegin(rg), rgsize, thisbgrgsizenew); + + this->controller.front_block = thisbgrgsize.itercontent; + this->controller.front_end_ptr = thisbgrgsize.itercontent.begin_ptr + block_size; + return {pos, thisbgrgsizenew}; + } + template <::std::ranges::range R> + requires ::std::constructible_from> + inline constexpr insert_range_result insert_range_back_impl(size_type pos, R &&rg, size_type old_size, size_type rgsize) noexcept(::std::is_nothrow_constructible_v>) + { + ::fast_io::containers::details::deque_reserve_back_spaces(this->controller, rgsize); + auto posit{this->begin() + pos}; + auto thisend{this->end()}; + auto thisendrgsize{thisend + rgsize}; + ::fast_io::freestanding::uninitialized_relocate_backward(posit, + thisend, thisendrgsize); + ::fast_io::freestanding::uninitialized_copy_n(::std::ranges::cbegin(rg), rgsize, posit); + if (thisendrgsize.itercontent.begin_ptr == thisendrgsize.itercontent.curr_ptr) + { + thisendrgsize.itercontent.curr_ptr = + (thisendrgsize.itercontent.begin_ptr = *--thisendrgsize.itercontent.controller_ptr) + block_size; + } + this->controller.back_block = thisendrgsize.itercontent; + this->controller.back_end_ptr = thisendrgsize.itercontent.begin_ptr + block_size; + return {pos, posit}; + } template <::std::ranges::range R> requires ::std::constructible_from> inline constexpr insert_range_result insert_range_impl(size_type pos, R &&rg, size_type old_size) noexcept(::std::is_nothrow_constructible_v>) @@ -2377,37 +2415,11 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE size_type const half_size{old_size >> 1u}; if (pos < half_size) { - ::fast_io::containers::details::deque_reserve_front_spaces(this->controller, rgsize); - auto thisbg{this->begin()}; - auto posit{thisbg + pos}; - auto thisbgrgsize{thisbg - rgsize}; - auto thisbgrgsizenew{::fast_io::freestanding::uninitialized_relocate(thisbg, - posit, thisbgrgsize)}; - ::fast_io::freestanding::uninitialized_copy_n(::std::ranges::cbegin(rg), rgsize, thisbgrgsizenew); - - this->controller.front_block = thisbgrgsize.itercontent; - this->controller.front_end_ptr = thisbgrgsize.itercontent.begin_ptr + block_size; - return {pos, thisbgrgsizenew}; + return this->insert_range_front_impl(pos, ::std::forward(rg), old_size, rgsize); } else { - ::fast_io::containers::details::deque_reserve_back_spaces(this->controller, rgsize); - auto posit{this->begin() + pos}; - auto thisend{this->end()}; - auto thisendrgsize{thisend + rgsize}; - ::fast_io::freestanding::uninitialized_relocate_backward(posit, - thisend, thisendrgsize); - ::fast_io::freestanding::uninitialized_copy_n(::std::ranges::cbegin(rg), rgsize, posit); - if (thisendrgsize.itercontent.begin_ptr == thisendrgsize.itercontent.curr_ptr) - { - thisendrgsize.itercontent.curr_ptr = - (thisendrgsize.itercontent.begin_ptr = *--thisendrgsize.itercontent.controller_ptr) + block_size; - } - this->controller.back_block = thisendrgsize.itercontent; - this->controller.back_end_ptr = thisendrgsize.itercontent.begin_ptr + block_size; - return {pos, posit}; + return this->insert_range_back_impl(pos, ::std::forward(rg), old_size, rgsize); } } else @@ -2447,7 +2459,7 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE inline constexpr iterator insert_range(const_iterator pos, R &&rg) noexcept(::std::is_nothrow_constructible_v>) { return this->insert_range_impl( - ::fast_io::containers::details::deque_iter_difference_unsigned_common(pos.itercontent, this->controller.front_block), rg, this->size()) + ::fast_io::containers::details::deque_iter_difference_unsigned_common(pos.itercontent, this->controller.front_block), ::std::forward(rg), this->size()) .it; } @@ -2460,7 +2472,7 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE { ::fast_io::fast_terminate(); } - return this->insert_range_impl(pos, rg, n).pos; + return this->insert_range_impl(pos, ::std::forward(rg), n).pos; } private: @@ -2492,22 +2504,35 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE requires ::std::constructible_from> inline constexpr void append_range(R &&rg) noexcept(::std::is_nothrow_constructible_v>) { - // To do: cleanup code - if constexpr (::std::is_nothrow_constructible_v>) + if constexpr (::std::ranges::sized_range) { - for (auto &e : rg) + size_type const rgsize{::std::ranges::size(rg)}; + if (!rgsize) { - this->push_back(e); + return; } + size_type const oldn{this->size()}; + this->insert_range_back_impl(oldn, ::std::forward(rg), oldn, rgsize); } else { - append_range_guard guard{this, this->size()}; - for (auto &e : rg) + // To do: cleanup code + if constexpr (::std::is_nothrow_constructible_v>) { - this->push_back(e); + for (auto &e : rg) + { + this->push_back(e); + } + } + else + { + append_range_guard guard{this, this->size()}; + for (auto &e : rg) + { + this->push_back(e); + } + guard.thisdeq = nullptr; } - guard.thisdeq = nullptr; } } #if 0 @@ -2531,27 +2556,39 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE ::std::is_nothrow_constructible_v> && ::std::is_nothrow_swappable_v) { - // To do: cleanup code - size_type oldn{this->size()}; - if constexpr ( - ::std::is_nothrow_constructible_v> && - ::std::is_nothrow_swappable_v) + if constexpr (::std::ranges::sized_range) { - for (auto &e : rg) + size_type const rgsize{::std::ranges::size(rg)}; + if (!rgsize) { - this->push_front(e); + return; } - ::std::reverse(this->begin(), this->end() - oldn); + return this->insert_range_front_impl(0, ::std::forward(rg), this->size(), rgsize); } else { - prepend_range_guard guard{this, oldn}; - for (auto &e : rg) + // To do: cleanup code + size_type oldn{this->size()}; + if constexpr ( + ::std::is_nothrow_constructible_v> && + ::std::is_nothrow_swappable_v) { - this->push_front(e); + for (auto &e : rg) + { + this->push_front(e); + } + ::std::reverse(this->begin(), this->end() - oldn); + } + else + { + prepend_range_guard guard{this, oldn}; + for (auto &e : rg) + { + this->push_front(e); + } + ::std::reverse(this->begin(), this->end() - oldn); + guard.thisdeq = nullptr; } - ::std::reverse(this->begin(), this->end() - oldn); - guard.thisdeq = nullptr; } } From ea4170811900cc1acd10ea1e23097a029c916b57 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 25 Mar 2026 05:15:29 +0800 Subject: [PATCH 2/3] deque prepend_range compilation should not return with typed value --- include/fast_io_dsal/impl/deque.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index 52f5f2c5..7744a662 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -2563,7 +2563,7 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE { return; } - return this->insert_range_front_impl(0, ::std::forward(rg), this->size(), rgsize); + this->insert_range_front_impl(0, ::std::forward(rg), this->size(), rgsize); } else { From bf6258b85ff66392715b9662a3eb0aee8a768cda Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 25 Mar 2026 05:26:19 +0800 Subject: [PATCH 3/3] implement insert_range internal --- include/fast_io_dsal/impl/deque.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/fast_io_dsal/impl/deque.h b/include/fast_io_dsal/impl/deque.h index 7744a662..ca6e41e2 100644 --- a/include/fast_io_dsal/impl/deque.h +++ b/include/fast_io_dsal/impl/deque.h @@ -2365,7 +2365,7 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE }; template <::std::ranges::range R> requires ::std::constructible_from> - inline constexpr insert_range_result insert_range_front_impl(size_type pos, R &&rg, size_type old_size, size_type rgsize) noexcept(::std::is_nothrow_constructible_v>) + inline constexpr insert_range_result insert_range_front_impl(size_type pos, R &&rg, size_type rgsize) noexcept(::std::is_nothrow_constructible_v>) { ::fast_io::containers::details::deque_reserve_front_spaces(this->controller, rgsize); @@ -2382,7 +2382,7 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE } template <::std::ranges::range R> requires ::std::constructible_from> - inline constexpr insert_range_result insert_range_back_impl(size_type pos, R &&rg, size_type old_size, size_type rgsize) noexcept(::std::is_nothrow_constructible_v>) + inline constexpr insert_range_result insert_range_back_impl(size_type pos, R &&rg, size_type rgsize) noexcept(::std::is_nothrow_constructible_v>) { ::fast_io::containers::details::deque_reserve_back_spaces(this->controller, rgsize); @@ -2415,11 +2415,11 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE size_type const half_size{old_size >> 1u}; if (pos < half_size) { - return this->insert_range_front_impl(pos, ::std::forward(rg), old_size, rgsize); + return this->insert_range_front_impl(pos, ::std::forward(rg), rgsize); } else { - return this->insert_range_back_impl(pos, ::std::forward(rg), old_size, rgsize); + return this->insert_range_back_impl(pos, ::std::forward(rg), rgsize); } } else @@ -2511,8 +2511,8 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE { return; } - size_type const oldn{this->size()}; - this->insert_range_back_impl(oldn, ::std::forward(rg), oldn, rgsize); + // To do write append specific code without using insert_range + this->insert_range_back_impl(this->size(), ::std::forward(rg), rgsize); } else { @@ -2563,7 +2563,7 @@ class deque FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE { return; } - this->insert_range_front_impl(0, ::std::forward(rg), this->size(), rgsize); + this->insert_range_front_impl(0, ::std::forward(rg), rgsize); } else {