Return a small allocation from realloc(ptr, 0). (#460)

An annoying amount of real-world code (e.g. mandoc, BSD sort) treats a
NULL return from `realloc` as a failure, even when requesting a size of
0.  This code is wrong (the standard explicitly permits a return of NULL
from realloc when given a size 0) but working around it in snmalloc is
easier than fixing it everywhere.
This commit is contained in:
David Chisnall
2022-02-11 15:11:15 +00:00
committed by GitHub
parent eb00f3184f
commit baf35cc80e
2 changed files with 14 additions and 2 deletions

View File

@@ -480,9 +480,14 @@ namespace snmalloc
{
return bits::next_pow2(size);
}
// If realloc(ptr, 0) returns nullptr, some consumers treat this as a
// reallocation failure and abort. To avoid this, we round up the size of
// requested allocations to the smallest size class. This can be changed
// on any platform that's happy to return nullptr from realloc(ptr,0) and
// should eventually become a configuration option.
if (size == 0)
{
return 0;
return sizeclass_to_size(size_to_sizeclass(1));
}
return sizeclass_to_size(size_to_sizeclass(size));
}

View File

@@ -36,12 +36,19 @@ void check_result(size_t size, size_t align, void* p, int err, bool null)
failed = true;
}
const auto alloc_size = our_malloc_usable_size(p);
const auto expected_size = round_size(size);
auto expected_size = round_size(size);
#ifdef SNMALLOC_PASS_THROUGH
// Calling system allocator may allocate a larger block than
// snmalloc. Note, we have called the system allocator with
// the size snmalloc would allocate, so it won't be smaller.
const auto exact_size = false;
// We allocate MIN_ALLOC_SIZE byte for 0-sized allocations (and so round_size
// will tell us that the minimum size is MIN_ALLOC_SIZE), but the system
// allocator may return a 0-sized allocation.
if (size == 0)
{
expected_size = 0;
}
#else
const auto exact_size = align == 1;
#endif