util: Return valid allocation for qemu_try_memalign() with zero size

Currently qemu_try_memalign()'s behaviour if asked to allocate
0 bytes is rather variable:
 * on Windows, we will assert
 * on POSIX platforms, we get the underlying behaviour of
   the posix_memalign() or equivalent function, which may be
   either "return a valid non-NULL pointer" or "return NULL"

Explictly check for 0 byte allocations, so we get consistent
behaviour across platforms.  We handle them by incrementing the size
so that we return a valid non-NULL pointer that can later be passed
to qemu_vfree().  This is permitted behaviour for the
posix_memalign() API and is the most usual way that underlying
malloc() etc implementations handle a zero-sized allocation request,
because it won't trip up calling code that assumes NULL means an
error.  (This includes our own qemu_memalign(), which will abort on
NULL.)

This change is a preparation for sharing the qemu_try_memalign() code
between Windows and POSIX.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
This commit is contained in:
Peter Maydell 2022-02-26 18:07:18 +00:00
parent ac8057a11b
commit bc0fecc1c2
2 changed files with 6 additions and 1 deletions

View File

@ -209,6 +209,9 @@ void *qemu_try_memalign(size_t alignment, size_t size)
g_assert(is_power_of_2(alignment)); g_assert(is_power_of_2(alignment));
} }
if (size == 0) {
size++;
}
#if defined(CONFIG_POSIX_MEMALIGN) #if defined(CONFIG_POSIX_MEMALIGN)
int ret; int ret;
ret = posix_memalign(&ptr, alignment, size); ret = posix_memalign(&ptr, alignment, size);

View File

@ -48,12 +48,14 @@ void *qemu_try_memalign(size_t alignment, size_t size)
{ {
void *ptr; void *ptr;
g_assert(size != 0);
if (alignment < sizeof(void *)) { if (alignment < sizeof(void *)) {
alignment = sizeof(void *); alignment = sizeof(void *);
} else { } else {
g_assert(is_power_of_2(alignment)); g_assert(is_power_of_2(alignment));
} }
if (size == 0) {
size++;
}
ptr = _aligned_malloc(size, alignment); ptr = _aligned_malloc(size, alignment);
trace_qemu_memalign(alignment, size, ptr); trace_qemu_memalign(alignment, size, ptr);
return ptr; return ptr;