Bug fixes (#752)
* Fix overflow by alignment * Bug fix: Ensure bytes_free is the total The bytes freed was not added to the total, but overrode it. This meant it never fired. This commit fixes that.
This commit is contained in:
committed by
GitHub
parent
5f7baef755
commit
6622dc584e
@@ -800,7 +800,7 @@ namespace snmalloc
|
||||
meta->as_key_tweak(),
|
||||
domesticate);
|
||||
|
||||
bytes_freed = objsize * length;
|
||||
bytes_freed += objsize * length;
|
||||
|
||||
// Update the head and the next pointer in the free list.
|
||||
meta->free_queue.append_segment(
|
||||
|
||||
@@ -129,17 +129,6 @@ namespace snmalloc
|
||||
|
||||
using sizeclass_compress_t = uint8_t;
|
||||
|
||||
constexpr SNMALLOC_FAST_PATH static size_t
|
||||
aligned_size(size_t alignment, size_t size)
|
||||
{
|
||||
// Client responsible for checking alignment is not zero
|
||||
SNMALLOC_ASSERT(alignment != 0);
|
||||
// Client responsible for checking alignment is a power of two
|
||||
SNMALLOC_ASSERT(bits::is_pow2(alignment));
|
||||
|
||||
return ((alignment - 1) | (size - 1)) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* This structure contains the fields required for fast paths for sizeclasses.
|
||||
*/
|
||||
@@ -535,4 +524,43 @@ namespace snmalloc
|
||||
return 1;
|
||||
return bits::one_at_bit(bits::ctz(rsize));
|
||||
}
|
||||
|
||||
constexpr SNMALLOC_FAST_PATH static size_t
|
||||
aligned_size(size_t alignment, size_t size)
|
||||
{
|
||||
// Client responsible for checking alignment is not zero
|
||||
SNMALLOC_ASSERT(alignment != 0);
|
||||
// Client responsible for checking alignment is a power of two
|
||||
SNMALLOC_ASSERT(bits::is_pow2(alignment));
|
||||
|
||||
// There are a class of corner cases to consider
|
||||
// alignment = 0x8
|
||||
// size = 0xfff...fff7
|
||||
// for this result will be 0. This should fail an allocation, so we need to
|
||||
// check for this overflow.
|
||||
// However,
|
||||
// alignment = 0x8
|
||||
// size = 0x0
|
||||
// will also result in 0, but this should be allowed to allocate.
|
||||
// So we need to check for overflow, and return SIZE_MAX in this first case,
|
||||
// and 0 in the second.
|
||||
size_t result = ((alignment - 1) | (size - 1)) + 1;
|
||||
// The following code is designed to fuse well with a subsequent
|
||||
// sizeclass calculation. We use the same fast path constant to
|
||||
// move the case where result==0 to the slow path, and then check for which
|
||||
// case we are in.
|
||||
constexpr size_t SmallSizeClassUpperBound =
|
||||
sizeclass_to_size(NUM_SMALL_SIZECLASSES - 1) - 1;
|
||||
if (SNMALLOC_LIKELY((result - 1) < SmallSizeClassUpperBound))
|
||||
return result;
|
||||
|
||||
// We are in the slow path, so we need to check for overflow.
|
||||
if (SNMALLOC_UNLIKELY(result == 0))
|
||||
{
|
||||
// Check for overflow and return the maximum size.
|
||||
if (SNMALLOC_UNLIKELY(result < size))
|
||||
return SIZE_MAX;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace snmalloc
|
||||
|
||||
@@ -15,11 +15,7 @@ constexpr int SUCCESS = 0;
|
||||
void check_result(size_t size, size_t align, void* p, int err, bool null)
|
||||
{
|
||||
bool failed = false;
|
||||
EXPECT(
|
||||
(errno == err) || (err == SUCCESS),
|
||||
"Expected error: {} but got {}",
|
||||
err,
|
||||
errno);
|
||||
EXPECT((errno == err), "Expected error: {} but got {}", err, errno);
|
||||
if (null)
|
||||
{
|
||||
EXPECT(p == nullptr, "Expected null but got {}", p);
|
||||
@@ -307,6 +303,9 @@ int main(int argc, char** argv)
|
||||
for (size_t align = sizeof(uintptr_t); align < MAX_SMALL_SIZECLASS_SIZE * 8;
|
||||
align <<= 1)
|
||||
{
|
||||
// Check overflow with alignment taking it round to 0.
|
||||
test_memalign(1 - align, align, ENOMEM, true);
|
||||
|
||||
for (smallsizeclass_t sc = 0; sc < NUM_SMALL_SIZECLASSES - 6; sc++)
|
||||
{
|
||||
const size_t size = sizeclass_to_size(sc);
|
||||
|
||||
Reference in New Issue
Block a user