Skip to content

Commit

Permalink
Fix masking of _First_used_block_idx in deque::shrink_to_fit
Browse files Browse the repository at this point in the history
  • Loading branch information
frederick-vs-ja committed Sep 13, 2024
1 parent 73b5791 commit 8a5d875
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 2 deletions.
6 changes: 4 additions & 2 deletions stl/inc/deque
Original file line number Diff line number Diff line change
Expand Up @@ -997,7 +997,8 @@ public:

const auto _Mask = static_cast<size_type>(_Mapsize() - 1);

const auto _First_used_block_idx = static_cast<size_type>(_Myoff() / _Block_size);
const auto _Unmasked_first_used_block_idx = static_cast<size_type>(_Myoff() / _Block_size);
const auto _First_used_block_idx = static_cast<size_type>(_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.
Expand All @@ -1017,7 +1018,8 @@ public:
}
}

const auto _Used_block_count = static_cast<size_type>(_Unmasked_first_unused_block_idx - _First_used_block_idx);
const auto _Used_block_count =
static_cast<size_type>(_Unmasked_first_unused_block_idx - _Unmasked_first_used_block_idx);

size_type _New_block_count = _Minimum_map_size; // should be power of 2

Expand Down
25 changes: 25 additions & 0 deletions tests/std/tests/GH_002769_handle_deque_block_pointers/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <iterator>
#include <memory>
Expand Down Expand Up @@ -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<int> qu;

long it = 0;
while (it < 1024) {
size_t numAlloc = rand() + 1;
for (size_t i = 0; i < numAlloc; i++) {
qu.push_back(0);
}

size_t numDealloc = 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();
}

0 comments on commit 8a5d875

Please sign in to comment.