From b810f96b5326a07887da9800ce40f0ec754f8692 Mon Sep 17 00:00:00 2001 From: Peter Gal Date: Fri, 6 Sep 2019 14:02:50 +0200 Subject: [PATCH] Fix TypedArray.slice with external array buffer In case of TypedArrays which were constructed with an ArrayBuffer the `slice` method incorrectly added the `byteOffset` value of when the elements were copied. There is no need to add the `byteOffset` value for the ArrayBuffer's contents pointer as it is already added by the `ecma_typedarray_get_buffer` call. JerryScript-DCO-1.0-Signed-off-by: Peter Gal pgal.u-szeged@partner.samsung.com --- .../ecma-builtin-typedarray-prototype.c | 3 +- .../es2015/regression-test-issue-3078.js | 21 ++++++ ...edarray-prototype-slice-ext-arraybuffer.js | 71 +++++++++++++++++++ 3 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 tests/jerry/es2015/regression-test-issue-3078.js create mode 100644 tests/jerry/es2015/typedarray-prototype-slice-ext-arraybuffer.js diff --git a/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c b/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c index 562817d0d5..f93d86ff59 100644 --- a/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c +++ b/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c @@ -1967,8 +1967,7 @@ ecma_builtin_typedarray_prototype_slice (ecma_value_t this_arg, /**< this argume ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray); lit_utf8_byte_t *new_typedarray_buffer_p = ecma_typedarray_get_buffer (new_typedarray_p); - ecma_length_t src_byte_offset = ecma_typedarray_get_offset (typedarray_p); - uint32_t src_byte_index = (start * element_size) + src_byte_offset; + uint32_t src_byte_index = (start * element_size); memcpy (new_typedarray_buffer_p, typedarray_buffer_p + src_byte_index, diff --git a/tests/jerry/es2015/regression-test-issue-3078.js b/tests/jerry/es2015/regression-test-issue-3078.js new file mode 100644 index 0000000000..ce3916ecda --- /dev/null +++ b/tests/jerry/es2015/regression-test-issue-3078.js @@ -0,0 +1,21 @@ +// Copyright JS Foundation and other contributors, http://js.foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var arrb = new ArrayBuffer(13); +var arr = new Uint8Array(arrb, 9); +for (var idx = 0; idx < arr.length; idx++) { + arr[idx] = idx + 1; +} + +assert(arr.slice(1).toString() == "2,3,4"); diff --git a/tests/jerry/es2015/typedarray-prototype-slice-ext-arraybuffer.js b/tests/jerry/es2015/typedarray-prototype-slice-ext-arraybuffer.js new file mode 100644 index 0000000000..9e4dd9bd69 --- /dev/null +++ b/tests/jerry/es2015/typedarray-prototype-slice-ext-arraybuffer.js @@ -0,0 +1,71 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var typedarrays = [ + Uint8ClampedArray, + Uint8Array, + Uint16Array, + Uint32Array, + Float32Array, + Float64Array, + Int8Array, + Int16Array, + Int32Array, +]; + +for (var typeIdx = 0; typeIdx < typedarrays.length; typeIdx++) { + var buffer = new ArrayBuffer(100); + var typed = new typedarrays[typeIdx](buffer, 8, 6); + try { + typed.prototype.slice.call(undefined); + assert(false); + } catch (err) { + assert(err instanceof TypeError); + } + + for (var idx = 0; idx < typed.length; idx++) { + typed[idx] = idx; + } + + // Test with normal inputs + assert(typed.slice(1, 3).toString() === "1,2"); + assert(typed.slice(2, 5).toString() === "2,3,4"); + assert(typed.slice(0, 6).toString() === "0,1,2,3,4,5"); + + // Test witn negative inputs + assert(typed.slice(-2, 5).toString() === "4"); + assert(typed.slice(0, -3).toString() === "0,1,2"); + assert(typed.slice(-1, -4).toString() === ""); + + // Test with bigger inputs then length + assert(typed.slice(7, 1).toString() === ""); + assert(typed.slice(2, 9).toString() === "2,3,4,5"); + + // Test with undefined + assert(typed.slice(undefined, 4).toString() === "0,1,2,3"); + assert(typed.slice(0, undefined).toString() === "0,1,2,3,4,5"); + assert(typed.slice(undefined, undefined).toString() === "0,1,2,3,4,5"); + + // Test with NaN and +/-Infinity + assert(typed.slice(NaN, 3).toString() === "0,1,2"); + assert(typed.slice(2, Infinity).toString() === "2,3,4,5"); + assert(typed.slice(-Infinity, Infinity).toString() === "0,1,2,3,4,5"); + + // Test with default inputs + assert(typed.slice().toString() === "0,1,2,3,4,5"); + assert(typed.slice(4).toString() === "4,5"); + + delete buffer; +}