Fix a bug in Pool::Deallocate

Reviewers: mferencevic, ipaljak

Reviewed By: mferencevic

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D2325
This commit is contained in:
Teon Banek 2019-08-26 13:35:28 +02:00
parent bb832de608
commit 1fa9d7752c
2 changed files with 28 additions and 0 deletions

View File

@ -220,10 +220,15 @@ void Pool::Deallocate(void *p) {
ptr < reinterpret_cast<uintptr_t>(chunk.data + data_size);
};
auto deallocate_block_from_chunk = [this, p](Chunk *chunk) {
// NOTE: This check is not enough to cover all double-free issues.
CHECK(chunk->blocks_available < blocks_per_chunk_)
<< "Deallocating more blocks than a chunk can contain, possibly a "
"double-free situation or we have a bug in the allocator.";
// Link the block into the free-list
auto *block = reinterpret_cast<unsigned char *>(p);
*block = chunk->first_available_block_ix;
chunk->first_available_block_ix = (block - chunk->data) / block_size_;
chunk->blocks_available++;
};
if (is_in_chunk(*last_dealloc_chunk_)) {
deallocate_block_from_chunk(last_dealloc_chunk_);

View File

@ -303,6 +303,29 @@ TEST(PoolResource, AllocationWithOverflow) {
}
}
TEST(PoolResource, BlockDeallocation) {
TestMemory test_mem;
const size_t max_blocks_per_chunk = 2U;
const size_t max_block_size = 64U;
utils::PoolResource mem(max_blocks_per_chunk, max_block_size, &test_mem);
auto *ptr = CheckAllocation(&mem, max_block_size);
test_mem.new_count_ = 0U;
// Do another allocation before deallocating `ptr`, so that we are sure that
// the chunk of 2 blocks is still alive and therefore `ptr` may be reused when
// it's deallocated. If we deallocate now, the implementation may choose to
// free the whole chunk, and we do not want that for the purposes of this
// test.
CheckAllocation(&mem, max_block_size);
EXPECT_EQ(test_mem.new_count_, 0U);
EXPECT_EQ(test_mem.delete_count_, 0U);
mem.Deallocate(ptr, max_block_size);
EXPECT_EQ(test_mem.delete_count_, 0U);
// CheckAllocation(&mem, max_block_size) will fail as PoolResource should
// reuse free blocks.
EXPECT_EQ(ptr, mem.Allocate(max_block_size));
EXPECT_EQ(test_mem.new_count_, 0U);
}
// NOLINTNEXTLINE(hicpp-special-member-functions)
class ContainerWithAllocatorLast final {
public: