From 7f72a9e314e69c6eac2a04ebb361aceaa433d3f6 Mon Sep 17 00:00:00 2001 From: RAJATH MOHARE Date: Fri, 30 Oct 2026 12:38:47 +0530 Subject: [PATCH 1/2] round up the expand-path pointer in msgpack_zone_malloc When the current chunk is full, msgpack_zone_malloc asks msgpack_zone_malloc_expand for size + MSGPACK_ZONE_ALIGN - 1 bytes and then rounded the returned pointer down instead of up into that padding. The pointer sits right after the new chunk's next link, so when MSGPACK_ZONE_ALIGN is stricter than the header's alignment the object started inside the header and its first bytes overwrote the link. That is the default 32-bit sparc build (MSGPACK_ZONE_ALIGN=8 with a 4-byte header) and any build that raises MSGPACK_ZONE_ALIGN; unpacking a large array was enough to make msgpack_zone_free follow the element's type tag as a chunk pointer. Round up, as the fast path and the C++ zone already do. The padding was already reserved, so allocation sizes are unchanged. --- include/msgpack/zone.h | 8 +++++++- test/CMakeLists.txt | 1 + test/zone_align_c.cpp | 28 ++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 test/zone_align_c.cpp diff --git a/include/msgpack/zone.h b/include/msgpack/zone.h index 500698f3b..3c27da975 100644 --- a/include/msgpack/zone.h +++ b/include/msgpack/zone.h @@ -125,7 +125,13 @@ static inline void* msgpack_zone_malloc(msgpack_zone* zone, size_t size) { void* ptr = msgpack_zone_malloc_expand(zone, size + (MSGPACK_ZONE_ALIGN - 1)); if (ptr) { - return (char*)((uintptr_t)(ptr) & ~(uintptr_t)(MSGPACK_ZONE_ALIGN - 1)); + /* round up into the padding reserved above; rounding down + * would hand out the new chunk's header */ + return (char*)( + (uintptr_t)( + (char*)ptr + (MSGPACK_ZONE_ALIGN - 1) + ) & ~(uintptr_t)(MSGPACK_ZONE_ALIGN - 1) + ); } } return NULL; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c098470a5..583a806ed 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -13,6 +13,7 @@ SET (check_PROGRAMS msgpack_c.cpp pack_unpack_c.cpp streaming_c.cpp + zone_align_c.cpp zone_c.cpp ) diff --git a/test/zone_align_c.cpp b/test/zone_align_c.cpp new file mode 100644 index 000000000..01b4e44af --- /dev/null +++ b/test/zone_align_c.cpp @@ -0,0 +1,28 @@ +/* msgpack_zone_malloc() is inline, so its alignment is fixed per translation + * unit. Use one stricter than the zone chunk header, as CMakeLists.txt does + * on sparc (MSGPACK_ZONE_ALIGN=8 with a 4-byte header), so that an object + * served from a newly expanded chunk needs padding. */ +#define MSGPACK_ZONE_ALIGN (2 * sizeof(void*)) + +#include + +#include + +#include + +TEST(zone, zone_c_malloc_expand_align) +{ + msgpack_zone z; + const size_t size = 4096; + EXPECT_TRUE(msgpack_zone_init(&z, 2048)); + /* larger than the chunk size: served by msgpack_zone_malloc_expand() */ + char* p = (char*)msgpack_zone_malloc(&z, size); + ASSERT_TRUE(p != NULL); + EXPECT_TRUE((uintptr_t)p % MSGPACK_ZONE_ALIGN == 0); + /* the object has to stay inside the size + MSGPACK_ZONE_ALIGN - 1 bytes + * reserved by the expansion, not overlap the new chunk's header */ + ASSERT_TRUE(p >= z.chunk_list.ptr - (size + MSGPACK_ZONE_ALIGN - 1)); + ASSERT_TRUE(p + size <= z.chunk_list.ptr); + memset(p, 0xff, size); + msgpack_zone_destroy(&z); +} From 124c6d9eae162fe4f7f0407c588308cc77e22c49 Mon Sep 17 00:00:00 2001 From: RAJATH MOHARE Date: Sun, 1 Nov 2026 21:24:20 +0530 Subject: [PATCH 2/2] undef MSGPACK_ZONE_ALIGN before overriding it in zone_align_c Building the tests with -DMSGPACK_ZONE_ALIGN=... in CXXFLAGS made the test's own #define a macro redefinition, which is an error under -Werror. --- test/zone_align_c.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/zone_align_c.cpp b/test/zone_align_c.cpp index 01b4e44af..8f126e8a4 100644 --- a/test/zone_align_c.cpp +++ b/test/zone_align_c.cpp @@ -2,6 +2,7 @@ * unit. Use one stricter than the zone chunk header, as CMakeLists.txt does * on sparc (MSGPACK_ZONE_ALIGN=8 with a 4-byte header), so that an object * served from a newly expanded chunk needs padding. */ +#undef MSGPACK_ZONE_ALIGN #define MSGPACK_ZONE_ALIGN (2 * sizeof(void*)) #include