51 lines
		
	
	
	
		
			2.3 KiB
			
		
	
	
	
		
			Diff
		
	
	
	
	
	
		
		
			
		
	
	
			51 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);
							 |