Skip to content

Commit 2e24a0b

Browse files
romandevMylesBorins
authored andcommittedApr 16, 2018
n-api: throw RangeError napi_create_typedarray()
According to the ECMA spec, we should throw a RangeError in the following cases: - `(length * elementSize) + offset` > the size of the array passed in - `offset % elementSize` != `0` In the current implementation, this check was omitted. So, the following code will cause a crash. ``` napi_create_typedarray(env, napi_uint16_array, 2 /* length */, buffer, 1 /* byte_offset */, &output_array); ``` This change fixes the problem and write some related tests. Refs: https://tc39.github.io/ecma262/#sec-typedarray-buffer-byteoffset-length Backport-PR-URL: #19447 PR-URL: #18037 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
1 parent fed2136 commit 2e24a0b

File tree

3 files changed

+85
-12
lines changed

3 files changed

+85
-12
lines changed
 

‎src/node_api.cc

+42-9
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,30 @@ struct napi_env__ {
149149
(!try_catch.HasCaught() ? napi_ok \
150150
: napi_set_last_error((env), napi_pending_exception))
151151

152+
#define THROW_RANGE_ERROR_IF_FALSE(env, condition, error, message) \
153+
do { \
154+
if (!(condition)) { \
155+
napi_throw_range_error((env), (error), (message)); \
156+
return napi_set_last_error((env), napi_generic_failure); \
157+
} \
158+
} while (0)
159+
160+
#define CREATE_TYPED_ARRAY( \
161+
env, type, size_of_element, buffer, byte_offset, length, out) \
162+
do { \
163+
if ((size_of_element) > 1) { \
164+
THROW_RANGE_ERROR_IF_FALSE( \
165+
(env), (byte_offset) % (size_of_element) == 0, \
166+
"ERR_NAPI_INVALID_TYPEDARRAY_ALIGNMENT", \
167+
"start offset of "#type" should be a multiple of "#size_of_element); \
168+
} \
169+
THROW_RANGE_ERROR_IF_FALSE((env), (length) * (size_of_element) + \
170+
(byte_offset) <= buffer->ByteLength(), \
171+
"ERR_NAPI_INVALID_TYPEDARRAY_LENGTH", \
172+
"Invalid typed array length"); \
173+
(out) = v8::type::New((buffer), (byte_offset), (length)); \
174+
} while (0)
175+
152176
namespace v8impl {
153177

154178
// convert from n-api property attributes to v8::PropertyAttribute
@@ -3157,31 +3181,40 @@ napi_status napi_create_typedarray(napi_env env,
31573181

31583182
switch (type) {
31593183
case napi_int8_array:
3160-
typedArray = v8::Int8Array::New(buffer, byte_offset, length);
3184+
CREATE_TYPED_ARRAY(
3185+
env, Int8Array, 1, buffer, byte_offset, length, typedArray);
31613186
break;
31623187
case napi_uint8_array:
3163-
typedArray = v8::Uint8Array::New(buffer, byte_offset, length);
3188+
CREATE_TYPED_ARRAY(
3189+
env, Uint8Array, 1, buffer, byte_offset, length, typedArray);
31643190
break;
31653191
case napi_uint8_clamped_array:
3166-
typedArray = v8::Uint8ClampedArray::New(buffer, byte_offset, length);
3192+
CREATE_TYPED_ARRAY(
3193+
env, Uint8ClampedArray, 1, buffer, byte_offset, length, typedArray);
31673194
break;
31683195
case napi_int16_array:
3169-
typedArray = v8::Int16Array::New(buffer, byte_offset, length);
3196+
CREATE_TYPED_ARRAY(
3197+
env, Int16Array, 2, buffer, byte_offset, length, typedArray);
31703198
break;
31713199
case napi_uint16_array:
3172-
typedArray = v8::Uint16Array::New(buffer, byte_offset, length);
3200+
CREATE_TYPED_ARRAY(
3201+
env, Uint16Array, 2, buffer, byte_offset, length, typedArray);
31733202
break;
31743203
case napi_int32_array:
3175-
typedArray = v8::Int32Array::New(buffer, byte_offset, length);
3204+
CREATE_TYPED_ARRAY(
3205+
env, Int32Array, 4, buffer, byte_offset, length, typedArray);
31763206
break;
31773207
case napi_uint32_array:
3178-
typedArray = v8::Uint32Array::New(buffer, byte_offset, length);
3208+
CREATE_TYPED_ARRAY(
3209+
env, Uint32Array, 4, buffer, byte_offset, length, typedArray);
31793210
break;
31803211
case napi_float32_array:
3181-
typedArray = v8::Float32Array::New(buffer, byte_offset, length);
3212+
CREATE_TYPED_ARRAY(
3213+
env, Float32Array, 4, buffer, byte_offset, length, typedArray);
31823214
break;
31833215
case napi_float64_array:
3184-
typedArray = v8::Float64Array::New(buffer, byte_offset, length);
3216+
CREATE_TYPED_ARRAY(
3217+
env, Float64Array, 8, buffer, byte_offset, length, typedArray);
31853218
break;
31863219
default:
31873220
return napi_set_last_error(env, napi_invalid_arg);

‎test/addons-napi/test_typedarray/test.js

+18
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,21 @@ arrayTypes.forEach((currentType) => {
5555
assert.notStrictEqual(theArray, template);
5656
assert.strictEqual(theArray.buffer, buffer);
5757
});
58+
59+
arrayTypes.forEach((currentType) => {
60+
const template = Reflect.construct(currentType, buffer);
61+
assert.throws(() => {
62+
test_typedarray.CreateTypedArray(template, buffer, 0, 136);
63+
}, /Invalid typed array length/);
64+
});
65+
66+
const nonByteArrayTypes = [ Int16Array, Uint16Array, Int32Array, Uint32Array,
67+
Float32Array, Float64Array ];
68+
nonByteArrayTypes.forEach((currentType) => {
69+
const template = Reflect.construct(currentType, buffer);
70+
assert.throws(() => {
71+
test_typedarray.CreateTypedArray(template, buffer,
72+
currentType.BYTES_PER_ELEMENT + 1, 1);
73+
console.log(`start of offset ${currentType}`);
74+
}, /start offset of/);
75+
});

‎test/addons-napi/test_typedarray/test_typedarray.c

+25-3
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,11 @@ napi_value External(napi_env env, napi_callback_info info) {
9797
}
9898

9999
napi_value CreateTypedArray(napi_env env, napi_callback_info info) {
100-
size_t argc = 2;
101-
napi_value args[2];
100+
size_t argc = 4;
101+
napi_value args[4];
102102
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
103103

104-
NAPI_ASSERT(env, argc == 2, "Wrong number of arguments");
104+
NAPI_ASSERT(env, argc == 2 || argc == 4, "Wrong number of arguments");
105105

106106
napi_value input_array = args[0];
107107
napi_valuetype valuetype0;
@@ -136,6 +136,28 @@ napi_value CreateTypedArray(napi_env env, napi_callback_info info) {
136136
NAPI_CALL(env, napi_get_typedarray_info(
137137
env, input_array, &type, &length, NULL, &in_array_buffer, &byte_offset));
138138

139+
if (argc == 4) {
140+
napi_valuetype valuetype2;
141+
NAPI_CALL(env, napi_typeof(env, args[2], &valuetype2));
142+
143+
NAPI_ASSERT(env, valuetype2 == napi_number,
144+
"Wrong type of arguments. Expects a number as third argument.");
145+
146+
uint32_t uint32_length;
147+
NAPI_CALL(env, napi_get_value_uint32(env, args[2], &uint32_length));
148+
length = uint32_length;
149+
150+
napi_valuetype valuetype3;
151+
NAPI_CALL(env, napi_typeof(env, args[3], &valuetype3));
152+
153+
NAPI_ASSERT(env, valuetype3 == napi_number,
154+
"Wrong type of arguments. Expects a number as third argument.");
155+
156+
uint32_t uint32_byte_offset;
157+
NAPI_CALL(env, napi_get_value_uint32(env, args[3], &uint32_byte_offset));
158+
byte_offset = uint32_byte_offset;
159+
}
160+
139161
napi_value output_array;
140162
NAPI_CALL(env, napi_create_typedarray(
141163
env, type, length, input_buffer, byte_offset, &output_array));

0 commit comments

Comments
 (0)
Please sign in to comment.