Skip to content

Commit 660f759

Browse files
indutnyjasnell
authored andcommitted
buffer: FreeCallback should be tied to ArrayBuffer
FreeCallback should be invoked on the storage disposal (`ArrayBuffer`), not when the view (`Uint8Array` or `Buffer`) is disposed. This causes bug and crashes in addons which create buffers and store only slices of them. PR-URL: #3198 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Trevor Norris <[email protected]>
1 parent 70c9e43 commit 660f759

File tree

4 files changed

+54
-1
lines changed

4 files changed

+54
-1
lines changed

src/node_buffer.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ MaybeLocal<Object> New(Environment* env,
353353
if (!mb.FromMaybe(false))
354354
return Local<Object>();
355355

356-
CallbackInfo::New(env->isolate(), ui, callback, hint);
356+
CallbackInfo::New(env->isolate(), ab, callback, hint);
357357
return scope.Escape(ui);
358358
}
359359

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include <node.h>
2+
#include <node_buffer.h>
3+
#include <util.h>
4+
#include <v8.h>
5+
6+
static int alive;
7+
static char buf[1024];
8+
9+
static void FreeCallback(char* data, void* hint) {
10+
alive--;
11+
}
12+
13+
void Alloc(const v8::FunctionCallbackInfo<v8::Value>& args) {
14+
v8::Isolate* isolate = args.GetIsolate();
15+
alive++;
16+
args.GetReturnValue().Set(node::Buffer::New(
17+
isolate,
18+
buf,
19+
sizeof(buf),
20+
FreeCallback,
21+
nullptr).ToLocalChecked());
22+
}
23+
24+
void Check(const v8::FunctionCallbackInfo<v8::Value>& args) {
25+
v8::Isolate* isolate = args.GetIsolate();
26+
isolate->RequestGarbageCollectionForTesting(
27+
v8::Isolate::kFullGarbageCollection);
28+
CHECK_GT(alive, 0);
29+
}
30+
31+
void init(v8::Local<v8::Object> target) {
32+
NODE_SET_METHOD(target, "alloc", Alloc);
33+
NODE_SET_METHOD(target, "check", Check);
34+
}
35+
36+
NODE_MODULE(binding, init);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
'targets': [
3+
{
4+
'target_name': 'binding',
5+
'sources': [ 'binding.cc' ]
6+
}
7+
]
8+
}
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
'use strict';
2+
// Flags: --expose-gc
3+
4+
var assert = require('assert');
5+
var binding = require('./build/Release/binding');
6+
var buf = binding.alloc();
7+
var slice = buf.slice(32);
8+
buf = null;
9+
binding.check(slice);

0 commit comments

Comments
 (0)