Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

n-api: throw RangeError in napi_create_dataview() with invalid range #17869

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -1313,6 +1313,12 @@ While using `N-API`, a constructor passed was not a function.

While using `N-API`, `Constructor.prototype` was not an object.

<a id="ERR_NAPI_INVALID_DATAVIEW_ARGS"></a>
### ERR_NAPI_INVALID_DATAVIEW_ARGS

While calling `napi_create_dataview()`, a given `offset` was outside the bounds
of the dataview or `offset + length` was larger than a length of given `buffer`.

<a id="ERR_NO_CRYPTO"></a>
### ERR_NO_CRYPTO

Expand Down
3 changes: 3 additions & 0 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,9 @@ E('ERR_MODULE_RESOLUTION_LEGACY', '%s not found by import in %s.' +
E('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times');
E('ERR_NAPI_CONS_FUNCTION', 'Constructor must be a function');
E('ERR_NAPI_CONS_PROTOTYPE_OBJECT', 'Constructor.prototype must be an object');
E('ERR_NAPI_INVALID_DATAVIEW_ARGS',
'byte_offset + byte_length should be less than or eqaul to the size in ' +
'bytes of the array passed in');
E('ERR_NO_CRYPTO', 'Node.js is not compiled with OpenSSL crypto support');
E('ERR_NO_ICU', '%s is not supported on Node.js compiled without ICU');
E('ERR_NO_LONGER_SUPPORTED', '%s is no longer supported');
Expand Down
8 changes: 8 additions & 0 deletions src/node_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3170,6 +3170,14 @@ napi_status napi_create_dataview(napi_env env,
RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);

v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
if (byte_length + byte_offset > buffer->ByteLength()) {
napi_throw_range_error(
env,
"ERR_NAPI_INVALID_DATAVIEW_ARGS",
"byte_offset + byte_length should be less than or "
"equal to the size in bytes of the array passed in");
return napi_set_last_error(env, napi_pending_exception);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, a crash occurred because there was no this line.

}
v8::Local<v8::DataView> DataView = v8::DataView::New(buffer, byte_offset,
byte_length);

Expand Down
22 changes: 16 additions & 6 deletions test/addons-napi/test_dataview/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,20 @@ const assert = require('assert');
// Testing api calls for arrays
const test_dataview = require(`./build/${common.buildType}/test_dataview`);

//create dataview
const buffer = new ArrayBuffer(128);
const template = Reflect.construct(DataView, [buffer]);
// Test for creating dataview
{
const buffer = new ArrayBuffer(128);
const template = Reflect.construct(DataView, [buffer]);

const theDataview = test_dataview.CreateDataView(template);
assert.ok(theDataview instanceof DataView,
`Expect ${theDataview} to be a DataView`);
const theDataview = test_dataview.CreateDataViewFromJSDataView(template);
assert.ok(theDataview instanceof DataView,
`Expect ${theDataview} to be a DataView`);
}

// Test for creating dataview with invalid range
{
const buffer = new ArrayBuffer(128);
assert.throws(() => {
test_dataview.CreateDataView(buffer, 10, 200);
}, RangeError);
}
52 changes: 51 additions & 1 deletion test/addons-napi/test_dataview/test_dataview.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,53 @@
#include "../common.h"

napi_value CreateDataView(napi_env env, napi_callback_info info) {
size_t argc = 3;
napi_value args [3];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));

NAPI_ASSERT(env, argc == 3, "Wrong number of arguments");

napi_valuetype valuetype0;
napi_value arraybuffer = args[0];

NAPI_CALL(env, napi_typeof(env, arraybuffer, &valuetype0));
NAPI_ASSERT(env, valuetype0 == napi_object,
"Wrong type of arguments. Expects a ArrayBuffer as the first "
"argument.");

bool is_arraybuffer;
NAPI_CALL(env, napi_is_arraybuffer(env, arraybuffer, &is_arraybuffer));
NAPI_ASSERT(env, is_arraybuffer,
"Wrong type of arguments. Expects a ArrayBuffer as the first "
"argument.");

napi_valuetype valuetype1;
NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));

NAPI_ASSERT(env, valuetype1 == napi_number,
"Wrong type of arguments. Expects a number as second argument.");

size_t byte_offset = 0;
NAPI_CALL(env, napi_get_value_uint32(env, args[1], (uint32_t*)(&byte_offset)));

napi_valuetype valuetype2;
NAPI_CALL(env, napi_typeof(env, args[2], &valuetype2));

NAPI_ASSERT(env, valuetype2 == napi_number,
"Wrong type of arguments. Expects a number as third argument.");

size_t length = 0;
NAPI_CALL(env, napi_get_value_uint32(env, args[2], (uint32_t*)(&length)));

napi_value output_dataview;
NAPI_CALL(env,
napi_create_dataview(env, length, arraybuffer,
byte_offset, &output_dataview));

return output_dataview;
}

napi_value CreateDataViewFromJSDataView(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args [1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
Expand Down Expand Up @@ -34,12 +81,15 @@ napi_value CreateDataView(napi_env env, napi_callback_info info) {
napi_create_dataview(env, length, buffer,
byte_offset, &output_dataview));


return output_dataview;
}

napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor descriptors[] = {
DECLARE_NAPI_PROPERTY("CreateDataView", CreateDataView)
DECLARE_NAPI_PROPERTY("CreateDataView", CreateDataView),
DECLARE_NAPI_PROPERTY("CreateDataViewFromJSDataView",
CreateDataViewFromJSDataView)
};

NAPI_CALL(env, napi_define_properties(
Expand Down