Skip to content

Commit 809386a

Browse files
committed
src: fix memory leak for v8.serialize
When Buffer::New passes in existing data, it cannot be garbage collected in js synchronous execution. Fixes: #40828 Refs: #38300
1 parent 4508c8c commit 809386a

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

src/node_serdes.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,10 @@ void SerializerContext::ReleaseBuffer(const FunctionCallbackInfo<Value>& args) {
209209
// Note: Both ValueSerializer and this Buffer::New() variant use malloc()
210210
// as the underlying allocator.
211211
std::pair<uint8_t*, size_t> ret = ctx->serializer_.Release();
212-
auto buf = Buffer::New(ctx->env(),
212+
auto buf = Buffer::Copy(ctx->env(),
213213
reinterpret_cast<char*>(ret.first),
214214
ret.second);
215+
free(ret.first);
215216

216217
if (!buf.IsEmpty()) {
217218
args.GetReturnValue().Set(buf.ToLocalChecked());
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
'use strict';
2+
// Flags: --expose-gc
3+
4+
require('../common');
5+
const v8 = require('v8');
6+
const assert = require('assert');
7+
8+
const before = process.memoryUsage.rss();
9+
10+
for (let i = 0; i < 1000000; i++) {
11+
v8.serialize('');
12+
}
13+
14+
global.gc();
15+
16+
const after = process.memoryUsage.rss();
17+
18+
if (process.config.variables.asan) {
19+
assert(before * 10 > after, `asan: before=${before} after=${after}`);
20+
} else {
21+
assert(after - before < 1024 * 1024 * 10, `before=${before} after=${after}`);
22+
}

0 commit comments

Comments
 (0)