From 5035178a1f31bc411358e4ec02f949fb1cc908ad Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Fri, 13 Sep 2024 18:46:55 +0800 Subject: [PATCH 1/2] Fix masking of `_First_used_block_idx` in `deque::shrink_to_fit` --- stl/inc/deque | 6 +++-- .../test.cpp | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/stl/inc/deque b/stl/inc/deque index 457136014d..15d9cefbf0 100644 --- a/stl/inc/deque +++ b/stl/inc/deque @@ -997,7 +997,8 @@ public: const auto _Mask = static_cast(_Mapsize() - 1); - const auto _First_used_block_idx = static_cast(_Myoff() / _Block_size); + const auto _Unmasked_first_used_block_idx = static_cast(_Myoff() / _Block_size); + const auto _First_used_block_idx = static_cast(_Unmasked_first_used_block_idx & _Mask); // (_Myoff() + _Mysize() - 1) is for the last element, i.e. the back() of the deque. // Divide by _Block_size to get the unmasked index of the last used block. @@ -1017,7 +1018,8 @@ public: } } - const auto _Used_block_count = static_cast(_Unmasked_first_unused_block_idx - _First_used_block_idx); + const auto _Used_block_count = + static_cast(_Unmasked_first_unused_block_idx - _Unmasked_first_used_block_idx); size_type _New_block_count = _Minimum_map_size; // should be power of 2 diff --git a/tests/std/tests/GH_002769_handle_deque_block_pointers/test.cpp b/tests/std/tests/GH_002769_handle_deque_block_pointers/test.cpp index 1d71a44c9e..07edf7df17 100644 --- a/tests/std/tests/GH_002769_handle_deque_block_pointers/test.cpp +++ b/tests/std/tests/GH_002769_handle_deque_block_pointers/test.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -328,8 +329,32 @@ void test_inconsistent_difference_types() { assert(counter == 0); } +// Also test GH-4954: Endless loop in deque::shrink_to_fit() +void test_gh_4954() { + deque qu; + + int it = 0; + while (it < 1024) { + const auto numAlloc = static_cast(rand() + 1); + for (size_t i = 0; i < numAlloc; i++) { + qu.push_back(0); + } + + auto numDealloc = static_cast(rand() + 1); + if (it % 100 == 0 || numDealloc > qu.size()) { + numDealloc = qu.size(); + } + for (size_t i = 0; i < numDealloc; i++) { + qu.pop_front(); + } + qu.shrink_to_fit(); + ++it; + } +} + int main() { test_gh_2769(); test_gh_3717(); + test_gh_4954(); test_inconsistent_difference_types(); } From b23f119286ca26a8befdd6cc5551e961270c474d Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Sat, 14 Sep 2024 07:33:49 +0800 Subject: [PATCH 2/2] Address @CaseyCarter's review comments --- .../test.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/tests/std/tests/GH_002769_handle_deque_block_pointers/test.cpp b/tests/std/tests/GH_002769_handle_deque_block_pointers/test.cpp index 07edf7df17..bdf2f345c9 100644 --- a/tests/std/tests/GH_002769_handle_deque_block_pointers/test.cpp +++ b/tests/std/tests/GH_002769_handle_deque_block_pointers/test.cpp @@ -4,10 +4,10 @@ #include #include #include -#include #include #include #include +#include #include using namespace std; @@ -332,23 +332,22 @@ void test_inconsistent_difference_types() { // Also test GH-4954: Endless loop in deque::shrink_to_fit() void test_gh_4954() { deque qu; + mt19937_64 mteng; - int it = 0; - while (it < 1024) { - const auto numAlloc = static_cast(rand() + 1); - for (size_t i = 0; i < numAlloc; i++) { + for (int i = 0; i < 256; ++i) { + const auto push_count = static_cast((mteng() & 32767U) + 1); + for (size_t j = 0; j < push_count; ++j) { qu.push_back(0); } - auto numDealloc = static_cast(rand() + 1); - if (it % 100 == 0 || numDealloc > qu.size()) { - numDealloc = qu.size(); + auto pop_count = static_cast((mteng() & 32767U) + 1); + if (i % 100 == 0 || pop_count > qu.size()) { + pop_count = qu.size(); } - for (size_t i = 0; i < numDealloc; i++) { + for (size_t j = 0; j < pop_count; ++j) { qu.pop_front(); } qu.shrink_to_fit(); - ++it; } }