Skip to content

Commit 55cfe37

Browse files
author
Gabriel Schulhof
committed
handle the case where the reference is not deleted in its destructor
1 parent 68dccb1 commit 55cfe37

File tree

3 files changed

+30
-7
lines changed

3 files changed

+30
-7
lines changed

src/js_native_api_v8.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,10 +281,10 @@ class RefBase : protected Finalizer, RefTracker {
281281
// this is safe because if a request to delete the reference
282282
// is made in the finalize_callback it will defer deletion
283283
// to this block and set _delete_self to true
284+
_finalize_ran = true;
285+
284286
if (_delete_self || is_env_teardown) {
285287
Delete(this);
286-
} else {
287-
_finalize_ran = true;
288288
}
289289
}
290290

test/js-native-api/test_reference_double_free/test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ const { buildType } = require('../../common');
77

88
const addon = require(`./build/${buildType}/test_reference_double_free`);
99

10-
{ new addon.MyObject(); }
10+
{ new addon.MyObject(true); }
11+
{ new addon.MyObject(false); }

test/js-native-api/test_reference_double_free/test_reference_double_free.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,41 @@
22
#include <js_native_api.h>
33
#include "../common.h"
44

5+
static size_t g_call_count = 0;
6+
57
static void Destructor(napi_env env, void* data, void* nothing) {
68
napi_ref* ref = data;
79
NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, *ref));
810
free(ref);
911
}
1012

13+
static void NoDeleteDestructor(napi_env env, void* data, void* hint) {
14+
napi_ref* ref = data;
15+
size_t* call_count = hint;
16+
17+
// This destructor must be called exactly once.
18+
if ((*call_count) > 0) abort();
19+
*call_count = ((*call_count) + 1);
20+
free(ref);
21+
}
22+
1123
static napi_value New(napi_env env, napi_callback_info info) {
12-
size_t argc = 0;
13-
napi_value js_this;
24+
size_t argc = 1;
25+
napi_value js_this, js_delete;
26+
bool delete;
1427
napi_ref* ref = malloc(sizeof(*ref));
1528

16-
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, NULL, &js_this, NULL));
17-
NODE_API_CALL(env, napi_wrap(env, js_this, ref, Destructor, NULL, ref));
29+
NODE_API_CALL(env,
30+
napi_get_cb_info(env, info, &argc, &js_delete, &js_this, NULL));
31+
NODE_API_CALL(env, napi_get_value_bool(env, js_delete, &delete));
32+
33+
if (delete) {
34+
NODE_API_CALL(env,
35+
napi_wrap(env, js_this, ref, Destructor, NULL, ref));
36+
} else {
37+
NODE_API_CALL(env,
38+
napi_wrap(env, js_this, ref, NoDeleteDestructor, &g_call_count, ref));
39+
}
1840
NODE_API_CALL(env, napi_reference_ref(env, *ref, NULL));
1941

2042
return js_this;

0 commit comments

Comments
 (0)