Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorGabriel Schulhof <gabriel.schulhof@intel.com>2021-02-10 09:52:54 +0300
committerMichaƫl Zasso <targos@protonmail.com>2021-02-28 16:39:56 +0300
commit27816eac61ca9b242fb716ff1fbf444416cbad0e (patch)
treeaa253c023925c3c4a6ec379c5470688fc8c5632f /test
parenta1ed78cb3ba653b3f76d9c1481e7033ba51ff88f (diff)
node-api: force env shutdown deferring behavior
The finalizer normally never gets called while a reference is strong. However, during environment shutdown all finalizers must get called. In order to unify the deferring behavior with that of a regular finalization, we must force the reference to be weak when we call its finalizer during environment shutdown. Fixes: https://github.com/nodejs/node/issues/37236 Co-authored-by: Chengzhong Wu <legendecas@gmail.com> PR-URL: https://github.com/nodejs/node/pull/37303 Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Michael Dawson <midawson@redhat.com>
Diffstat (limited to 'test')
-rw-r--r--test/js-native-api/test_reference_double_free/binding.gyp11
-rw-r--r--test/js-native-api/test_reference_double_free/test.js11
-rw-r--r--test/js-native-api/test_reference_double_free/test_reference_double_free.c55
3 files changed, 77 insertions, 0 deletions
diff --git a/test/js-native-api/test_reference_double_free/binding.gyp b/test/js-native-api/test_reference_double_free/binding.gyp
new file mode 100644
index 00000000000..864846765d0
--- /dev/null
+++ b/test/js-native-api/test_reference_double_free/binding.gyp
@@ -0,0 +1,11 @@
+{
+ "targets": [
+ {
+ "target_name": "test_reference_double_free",
+ "sources": [
+ "../entry_point.c",
+ "test_reference_double_free.c"
+ ]
+ }
+ ]
+}
diff --git a/test/js-native-api/test_reference_double_free/test.js b/test/js-native-api/test_reference_double_free/test.js
new file mode 100644
index 00000000000..242d850ba9f
--- /dev/null
+++ b/test/js-native-api/test_reference_double_free/test.js
@@ -0,0 +1,11 @@
+'use strict';
+
+// This test makes no assertions. It tests a fix without which it will crash
+// with a double free.
+
+const { buildType } = require('../../common');
+
+const addon = require(`./build/${buildType}/test_reference_double_free`);
+
+{ new addon.MyObject(true); }
+{ new addon.MyObject(false); }
diff --git a/test/js-native-api/test_reference_double_free/test_reference_double_free.c b/test/js-native-api/test_reference_double_free/test_reference_double_free.c
new file mode 100644
index 00000000000..48491ea2aae
--- /dev/null
+++ b/test/js-native-api/test_reference_double_free/test_reference_double_free.c
@@ -0,0 +1,55 @@
+#include <stdlib.h>
+#include <js_native_api.h>
+#include "../common.h"
+
+static size_t g_call_count = 0;
+
+static void Destructor(napi_env env, void* data, void* nothing) {
+ napi_ref* ref = data;
+ NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, *ref));
+ free(ref);
+}
+
+static void NoDeleteDestructor(napi_env env, void* data, void* hint) {
+ napi_ref* ref = data;
+ size_t* call_count = hint;
+
+ // This destructor must be called exactly once.
+ if ((*call_count) > 0) abort();
+ *call_count = ((*call_count) + 1);
+ free(ref);
+}
+
+static napi_value New(napi_env env, napi_callback_info info) {
+ size_t argc = 1;
+ napi_value js_this, js_delete;
+ bool delete;
+ napi_ref* ref = malloc(sizeof(*ref));
+
+ NODE_API_CALL(env,
+ napi_get_cb_info(env, info, &argc, &js_delete, &js_this, NULL));
+ NODE_API_CALL(env, napi_get_value_bool(env, js_delete, &delete));
+
+ if (delete) {
+ NODE_API_CALL(env,
+ napi_wrap(env, js_this, ref, Destructor, NULL, ref));
+ } else {
+ NODE_API_CALL(env,
+ napi_wrap(env, js_this, ref, NoDeleteDestructor, &g_call_count, ref));
+ }
+ NODE_API_CALL(env, napi_reference_ref(env, *ref, NULL));
+
+ return js_this;
+}
+
+EXTERN_C_START
+napi_value Init(napi_env env, napi_value exports) {
+ napi_value myobj_ctor;
+ NODE_API_CALL(env,
+ napi_define_class(
+ env, "MyObject", NAPI_AUTO_LENGTH, New, NULL, 0, NULL, &myobj_ctor));
+ NODE_API_CALL(env,
+ napi_set_named_property(env, exports, "MyObject", myobj_ctor));
+ return exports;
+}
+EXTERN_C_END