diff --git a/jerry-core/ecma/operations/ecma-array-object.c b/jerry-core/ecma/operations/ecma-array-object.c index bf5adcf0a5..b3853e2293 100644 --- a/jerry-core/ecma/operations/ecma-array-object.c +++ b/jerry-core/ecma/operations/ecma-array-object.c @@ -244,7 +244,7 @@ ecma_fast_array_set_property (ecma_object_t *object_p, /**< fast access mode arr if (ecma_is_value_array_hole (values_p[index])) { - ext_obj_p->u.array.hole_count--; + ext_obj_p->u.array.hole_count = (uint8_t) JERRY_MAX (ext_obj_p->u.array.hole_count - 1, 0); } else { @@ -269,10 +269,14 @@ ecma_fast_array_set_property (ecma_object_t *object_p, /**< fast access mode arr values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); JERRY_ASSERT (ecma_is_value_array_hole (values_p[index])); ext_obj_p->u.array.length = new_length; + ext_obj_p->u.array.hole_count = (uint8_t) JERRY_MIN (ext_obj_p->u.array.hole_count + new_holes, + ECMA_FAST_ARRAY_MAX_HOLE_COUNT); } else { - if ((new_holes + ext_obj_p->u.array.hole_count) > ECMA_FAST_ARRAY_MAX_HOLE_COUNT) + JERRY_ASSERT (ext_obj_p->u.array.hole_count <= ECMA_FAST_ARRAY_MAX_HOLE_COUNT); + + if (new_holes > (uint32_t) (ECMA_FAST_ARRAY_MAX_HOLE_COUNT - ext_obj_p->u.array.hole_count)) { ecma_fast_array_convert_to_normal (object_p); @@ -280,10 +284,10 @@ ecma_fast_array_set_property (ecma_object_t *object_p, /**< fast access mode arr } values_p = ecma_fast_array_extend (object_p, new_length); + ext_obj_p->u.array.hole_count = (uint8_t) (ext_obj_p->u.array.hole_count + new_holes); } values_p[index] = ecma_copy_value_if_not_object (value); - ext_obj_p->u.array.hole_count = (uint8_t) (ext_obj_p->u.array.hole_count + new_holes); return true; } /* ecma_fast_array_set_property */ @@ -372,7 +376,11 @@ ecma_array_object_delete_property (ecma_object_t *object_p, /**< object */ ecma_free_value_if_not_object (values_p[index]); values_p[index] = ECMA_VALUE_ARRAY_HOLE; - ext_obj_p->u.array.hole_count++; + + if (++ext_obj_p->u.array.hole_count > ECMA_FAST_ARRAY_MAX_HOLE_COUNT) + { + ecma_fast_array_convert_to_normal (object_p); + } } /* ecma_array_object_delete_property */ /** @@ -416,7 +424,7 @@ ecma_delete_fast_array_properties (ecma_object_t *object_p, /**< fast access mod { if (ecma_is_value_array_hole (values_p[i])) { - ext_obj_p->u.array.hole_count--; + ext_obj_p->u.array.hole_count = (uint8_t) JERRY_MAX (ext_obj_p->u.array.hole_count - 1, 0); } else { @@ -469,7 +477,9 @@ ecma_fast_array_set_length (ecma_object_t *object_p, /**< fast access mode array uint32_t new_holes = new_length - old_length - 1; - if ((new_holes + ext_obj_p->u.array.hole_count) > ECMA_FAST_ARRAY_MAX_HOLE_COUNT) + JERRY_ASSERT (ext_obj_p->u.array.hole_count <= ECMA_FAST_ARRAY_MAX_HOLE_COUNT); + + if (new_holes > (uint32_t) (ECMA_FAST_ARRAY_MAX_HOLE_COUNT - ext_obj_p->u.array.hole_count)) { ecma_fast_array_convert_to_normal (object_p); return; diff --git a/tests/jerry/regression-test-issue-3060.js b/tests/jerry/regression-test-issue-3060.js new file mode 100644 index 0000000000..a08e2b3ef3 --- /dev/null +++ b/tests/jerry/regression-test-issue-3060.js @@ -0,0 +1,24 @@ +// 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 arr = []; +arr.length = 10; +arr.splice(0, 17); +arr.length = 4294967294; +arr.splice(1, 1, 1); + +assert(arr.length === 4294967294); +assert(arr[0] === undefined); +assert(arr[1] === 1); +assert(arr[2] === undefined);