From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Jeroen Hofstee Date: Tue, 1 Apr 2025 20:09:31 +0000 Subject: zlib: fix pointer alignment The function AllocForBrotli prefixes the allocated memory with its size, and returns a pointer to the region after it. This pointer can however no longer be suitably aligned. Correct this by allocating the maximum of the the size of the size_t and the max alignment. On Arm 32bits the size_t is 4 bytes long, but the alignment is 8 for some NEON instructions. When Brotli is compiled with optimizations enabled newer GCC versions will use the NEON instructions and trigger a bus error killing node. see https://github.com/google/brotli/issues/1159 diff --git a/src/node_zlib.cc b/src/node_zlib.cc index 90307cd4984ae5aa55386f2980ad9cd540322dfd..6f12b5034d1a98da50c064cf2cfdf12fc88137eb 100644 --- a/src/node_zlib.cc +++ b/src/node_zlib.cc @@ -493,7 +493,8 @@ class CompressionStream : public AsyncWrap, public ThreadPoolWork { } static void* AllocForBrotli(void* data, size_t size) { - size += sizeof(size_t); + constexpr size_t offset = std::max(sizeof(size_t), alignof(max_align_t)); + size += offset; CompressionStream* ctx = static_cast(data); char* memory = UncheckedMalloc(size); if (memory == nullptr) [[unlikely]] { @@ -502,7 +503,7 @@ class CompressionStream : public AsyncWrap, public ThreadPoolWork { *reinterpret_cast(memory) = size; ctx->unreported_allocations_.fetch_add(size, std::memory_order_relaxed); - return memory + sizeof(size_t); + return memory + offset; } static void FreeForZlib(void* data, void* pointer) { @@ -510,7 +511,8 @@ class CompressionStream : public AsyncWrap, public ThreadPoolWork { return; } CompressionStream* ctx = static_cast(data); - char* real_pointer = static_cast(pointer) - sizeof(size_t); + constexpr size_t offset = std::max(sizeof(size_t), alignof(max_align_t)); + char* real_pointer = static_cast(pointer) - offset; size_t real_size = *reinterpret_cast(real_pointer); ctx->unreported_allocations_.fetch_sub(real_size, std::memory_order_relaxed);