Skip to content

Commit cff72f1

Browse files
committed
Fix bug with copying deallocated bucket_container.
We should be able to copy a deallocated bucket container, but we would originally have been trying to access memory from a nullptr. In this case, the copied buckets pointer should just be nullptr as well.
1 parent 784d0f5 commit cff72f1

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

libcuckoo/bucket_container.hh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,14 @@ public:
244244
destroy_buckets();
245245
}
246246

247+
// Checks whether the bucket container owns any memory, or if has been
248+
// deallocated. If true, the member-wise getter/setter operations will be
249+
// valid, otherwise they cannot be called safely. Object-level members (such
250+
// as hashpower and size) will remain valid after deallocation.
251+
explicit operator bool() const noexcept {
252+
return buckets_ != nullptr;
253+
}
254+
247255
private:
248256
using bucket_traits_ = typename traits_::template rebind_traits<bucket>;
249257
using bucket_pointer = typename bucket_traits_::pointer;
@@ -321,6 +329,7 @@ private:
321329
const bucket_container &>::type src,
322330
std::integral_constant<bool, B> move) {
323331
assert(dst_hp >= src.hashpower());
332+
if (!static_cast<bool>(src)) { return nullptr; }
324333
bucket_container dst(dst_hp, get_allocator());
325334
// Move/copy all occupied slots of the source buckets
326335
for (size_t i = 0; i < src.size(); ++i) {

tests/unit-tests/test_bucket_container.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,3 +327,16 @@ TEST_CASE("copy assignment with throwing type is destroyed properly",
327327
REQUIRE_THROWS_AS(other = container, std::runtime_error);
328328
ExceptionInt::do_throw = false;
329329
}
330+
331+
TEST_CASE("copy destroyed buckets container", "[bucket container]") {
332+
std::allocator<value_type> a;
333+
TestingContainer<decltype(a)> bc(2, a);
334+
REQUIRE(static_cast<bool>(bc));
335+
bc.clear_and_deallocate();
336+
REQUIRE(!static_cast<bool>(bc));
337+
auto bc2 = bc;
338+
REQUIRE(!static_cast<bool>(bc));
339+
REQUIRE(!static_cast<bool>(bc2));
340+
REQUIRE(bc.size() == bc2.size());
341+
REQUIRE(bc.get_allocator() == bc2.get_allocator());
342+
}

0 commit comments

Comments
 (0)