From 9d77c4191030576fd502faa04148b52fa6dbcb43 Mon Sep 17 00:00:00 2001 From: Yaksh Bariya Date: Mon, 25 Aug 2025 14:19:59 +0530 Subject: [PATCH] src: correctly report memory changes to V8 Call `V8::ExternalMemoryAccounter::Update` instead of `V8::ExternalMemoryAccounter::Increase` to report memory difference to V8 Calling `V8::ExternalMemoryAccounter::Increase` with a signed integer on 32-bit platforms causes instances where GC inside GC takes place leading to a crash in certain cases. During GC, native objects are destructed. In destructor for `CompressionStream` class used by zlib, memory release information is passed onto `V8::ExternalMemoryAccounter::Increase()` instead of `V8::ExternalMemoryAccounter::Decrease()` which triggers V8's memory limits, thus triggering GC inside GC which leads to crash. Bug initially introduced in commit 1d5d7b6eedb2274c9ad48b5f378598a10479e4a7 For full report see https://hackerone.com/reports/3302484 --- src/node_mem-inl.h | 2 +- src/node_zlib.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/node_mem-inl.h b/src/node_mem-inl.h index 06871d031d36f6..70d28dd524be84 100644 --- a/src/node_mem-inl.h +++ b/src/node_mem-inl.h @@ -59,7 +59,7 @@ void* NgLibMemoryManager::ReallocImpl(void* ptr, // Environment*/Isolate* parameter and call the V8 method transparently. const int64_t new_size = size - previous_size; manager->IncreaseAllocatedSize(new_size); - manager->env()->external_memory_accounter()->Increase( + manager->env()->external_memory_accounter()->Update( manager->env()->isolate(), new_size); *reinterpret_cast(mem) = size; mem += sizeof(size_t); diff --git a/src/node_zlib.cc b/src/node_zlib.cc index c088c54753989f..b8617093bdf5a6 100644 --- a/src/node_zlib.cc +++ b/src/node_zlib.cc @@ -644,7 +644,7 @@ class CompressionStream : public AsyncWrap, public ThreadPoolWork { if (report == 0) return; CHECK_IMPLIES(report < 0, zlib_memory_ >= static_cast(-report)); zlib_memory_ += report; - AsyncWrap::env()->external_memory_accounter()->Increase( + AsyncWrap::env()->external_memory_accounter()->Update( AsyncWrap::env()->isolate(), report); }