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..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 @@ -7,6 +7,7 @@ #include #include #include +#include #include using namespace std; @@ -328,8 +329,31 @@ 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; + mt19937_64 mteng; + + 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 pop_count = static_cast((mteng() & 32767U) + 1); + if (i % 100 == 0 || pop_count > qu.size()) { + pop_count = qu.size(); + } + for (size_t j = 0; j < pop_count; ++j) { + qu.pop_front(); + } + qu.shrink_to_fit(); + } +} + int main() { test_gh_2769(); test_gh_3717(); + test_gh_4954(); test_inconsistent_difference_types(); }