Skip to content

Commit

Permalink
test: store external type tags by value (#114)
Browse files Browse the repository at this point in the history
  • Loading branch information
toyobayashi authored Apr 15, 2024
1 parent 18de1ab commit c6a802c
Showing 1 changed file with 33 additions and 4 deletions.
37 changes: 33 additions & 4 deletions packages/test/object/test_object.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#define NAPI_EXPERIMENTAL
#include <js_native_api.h>

#if !defined(__wasm__) || (defined(__EMSCRIPTEN__) || defined(__wasi__))
#include <string.h>
#else
void* memset(void *dst, int c, size_t n);
#endif

#include "../common.h"
#include "../entry_point.h"
// #include <string.h>
Expand Down Expand Up @@ -634,12 +640,29 @@ TypeTaggedInstance(napi_env env, napi_callback_info info) {
size_t argc = 1;
uint32_t type_index;
napi_value instance, which_type;
napi_type_tag tag;

// Below we copy the tag before setting it to prevent bugs where a pointer
// to the tag (instead of the 128-bit tag value) is stored.

NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &which_type, NULL, NULL));
NODE_API_CALL(env, napi_get_value_uint32(env, which_type, &type_index));
VALIDATE_TYPE_INDEX(env, type_index);
NODE_API_CALL(env, napi_create_object(env, &instance));
NODE_API_CALL(env, napi_type_tag_object(env, instance, &type_tags[type_index]));
tag = type_tags[type_index];
NODE_API_CALL(env, napi_type_tag_object(env, instance, &tag));

// Since the tag passed to napi_type_tag_object() was copied to the stack,
// a type tagging implementation that uses a pointer instead of the
// tag value would end up pointing to stack memory.
// When CheckTypeTag() is called later on, it might be the case that this
// stack address has been left untouched by accident (if no subsequent
// function call has clobbered it), which means the pointer would still
// point to valid data.
// To make sure that tags are stored by value and not by reference,
// clear this copy; any implementation using a pointer would end up with
// random stack data or { 0, 0 }, but not the original tag value, and fail.
memset(&tag, 0, sizeof(tag));

return instance;
}
Expand All @@ -660,15 +683,21 @@ static napi_value TypeTaggedExternal(napi_env env, napi_callback_info info) {
size_t argc = 1;
uint32_t type_index;
napi_value instance, which_type;
napi_type_tag tag;

// See TypeTaggedInstance() for an explanation about why we copy the tag
// to the stack and why we call memset on it after the external is tagged.

NODE_API_CALL(env,
napi_get_cb_info(env, info, &argc, &which_type, NULL, NULL));
NODE_API_CALL(env, napi_get_value_uint32(env, which_type, &type_index));
VALIDATE_TYPE_INDEX(env, type_index);
NODE_API_CALL(
env, napi_create_external(env, IN_LIEU_OF_NULL, NULL, NULL, &instance));
NODE_API_CALL(env,
napi_type_tag_object(env, instance, &type_tags[type_index]));
tag = type_tags[type_index];
NODE_API_CALL(env, napi_type_tag_object(env, instance, &tag));

memset(&tag, 0, sizeof(tag));

return instance;
}
Expand Down

0 comments on commit c6a802c

Please sign in to comment.