diff --git a/src/runtime/runtime-array.cc b/src/runtime/runtime-array.cc index 714da4ff4a..5346658798 100644 --- a/src/runtime/runtime-array.cc +++ b/src/runtime/runtime-array.cc @@ -139,8 +139,15 @@ Object RemoveArrayHolesGeneric(Isolate* isolate, Handle receiver, } } + // current_pos points to the next free space in the array/object. In most + // cases this corresponds to the 'length' or to the number of non-undefined + // elements. + // In cases where an object is 'packed' and 'length' is smaller, e.g.: + // { 0: 5, 1: 4, 2: 3, length: 2 } + // current_pos will be greater than limit, thus, we need to take the minimum. + uint32_t result = std::min(current_pos, limit); + // Set [current_pos, current_pos + num_undefined) to undefined. - uint32_t result = current_pos; for (uint32_t i = 0; i < num_undefined; ++i) { RETURN_FAILURE_ON_EXCEPTION( isolate, Object::SetElement(isolate, receiver, current_pos++, @@ -162,10 +169,6 @@ Object RemoveArrayHolesGeneric(Isolate* isolate, Handle receiver, MAYBE_RETURN(delete_result, ReadOnlyRoots(isolate).exception()); } - // The number of non-undefined elements MUST always be smaller then limit. - // Violating this may cause OOB reads/writes. - CHECK_LE(result, limit); - return *isolate->factory()->NewNumberFromUint(result); } diff --git a/test/mjsunit/regress/regress-crbug-923265.js b/test/mjsunit/regress/regress-crbug-923265.js new file mode 100644 index 0000000000..8e6125b34b --- /dev/null +++ b/test/mjsunit/regress/regress-crbug-923265.js @@ -0,0 +1,9 @@ +// Copyright 2019 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +let a = {0: 5, 1: 4, 2: 3, length: 2}; +Object.freeze(a); + +assertThrows(() => Array.prototype.sort.call(a)); +assertPropertiesEqual({0: 5, 1: 4, 2: 3, length: 2}, a);