mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-07-08 06:47:18 +03:00
free_sized() and free_aligned_sized() forward straight to sdallocx(), which expects a non-NULL pointer and asserts on it in debug builds. C23 says both should accept NULL and do nothing, like free(NULL) does, so a NULL argument either trips that assert or feeds NULL into the dealloc path in release builds. It is not hard to hit. glibc 2.41 ships free_sized()/free_aligned_sized(), and a C++ sized delete of a null pointer compiles down to a free_sized() call. Once jemalloc is preloaded its versions take over, and that NULL call takes down the process. I ran into it with GTK4/GLib apps under LD_PRELOAD. Check for NULL first, the way free() already does, and add an integration test covering the NULL case for both functions. While here, give free_aligned_sized() its own core.free_aligned_sized.entry and .exit logging and call je_sdallocx_impl() directly rather than the je_sdallocx() wrapper, so it mirrors free_sized() and no longer logs under sdallocx. The C++ sized-delete paths (sizedDeleteImpl, alignedSizedDeleteImpl) get the same treatment: log entry/exit unconditionally and guard the call with likely(ptr != nullptr).
37 lines
879 B
C
37 lines
879 B
C
#include "test/jemalloc_test.h"
|
|
|
|
TEST_BEGIN(test_free_sized) {
|
|
void *p = mallocx(42, 0);
|
|
expect_ptr_not_null(p, "Unexpected mallocx() failure");
|
|
free_sized(p, 42);
|
|
}
|
|
TEST_END
|
|
|
|
TEST_BEGIN(test_free_aligned_sized) {
|
|
size_t alignment = 0x100;
|
|
void *p = mallocx(42, MALLOCX_ALIGN(alignment));
|
|
expect_ptr_not_null(p, "Unexpected mallocx() failure");
|
|
free_aligned_sized(p, alignment, 42);
|
|
}
|
|
TEST_END
|
|
|
|
TEST_BEGIN(test_free_sized_null) {
|
|
/*
|
|
* C23 specifies that free_sized(NULL, size) and
|
|
* free_aligned_sized(NULL, alignment, size) do nothing, just as
|
|
* free(NULL) does. The size argument is ignored for a NULL pointer.
|
|
*/
|
|
free_sized(NULL, 0);
|
|
free_sized(NULL, 42);
|
|
free_aligned_sized(NULL, 0x100, 0);
|
|
free_aligned_sized(NULL, 0x100, 42);
|
|
}
|
|
TEST_END
|
|
|
|
int
|
|
main(void) {
|
|
return test(
|
|
test_free_sized,
|
|
test_free_aligned_sized,
|
|
test_free_sized_null);
|
|
}
|