fix: fix zlib pointer alignment Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
		
			
				
	
	
		
			50 lines
		
	
	
	
		
			2.3 KiB
			
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			50 lines
		
	
	
	
		
			2.3 KiB
			
		
	
	
	
		
			Diff
		
	
	
	
	
	
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
						|
From: Jeroen Hofstee <jhofstee@victronenergy.com>
 | 
						|
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<CompressionStream*>(data);
 | 
						|
     char* memory = UncheckedMalloc(size);
 | 
						|
     if (memory == nullptr) [[unlikely]] {
 | 
						|
@@ -502,7 +503,7 @@ class CompressionStream : public AsyncWrap, public ThreadPoolWork {
 | 
						|
     *reinterpret_cast<size_t*>(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<CompressionStream*>(data);
 | 
						|
-    char* real_pointer = static_cast<char*>(pointer) - sizeof(size_t);
 | 
						|
+    constexpr size_t offset = std::max(sizeof(size_t), alignof(max_align_t));
 | 
						|
+    char* real_pointer = static_cast<char*>(pointer) - offset;
 | 
						|
     size_t real_size = *reinterpret_cast<size_t*>(real_pointer);
 | 
						|
     ctx->unreported_allocations_.fetch_sub(real_size,
 | 
						|
                                            std::memory_order_relaxed);
 |