Array.prototype.sort: Unchecked calls to hasOwnProperty and push and sort
BUG=v8:3537 LOG= R=arv@chromium.org, wingo@igalia.com, yangguo@chromium.org Review URL: https://codereview.chromium.org/555173002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24005 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
6cbeb6d00e
commit
00375fba59
23
src/array.js
23
src/array.js
@ -863,11 +863,12 @@ function ArraySort(comparefn) {
|
||||
var t_array = [];
|
||||
// Use both 'from' and 'to' to determine the pivot candidates.
|
||||
var increment = 200 + ((to - from) & 15);
|
||||
for (var i = from + 1; i < to - 1; i += increment) {
|
||||
t_array.push([i, a[i]]);
|
||||
for (var i = from + 1, j = 0; i < to - 1; i += increment, j++) {
|
||||
t_array[j] = [i, a[i]];
|
||||
}
|
||||
t_array.sort(function(a, b) {
|
||||
return %_CallFunction(receiver, a[1], b[1], comparefn) } );
|
||||
%_CallFunction(t_array, function(a, b) {
|
||||
return %_CallFunction(receiver, a[1], b[1], comparefn);
|
||||
}, ArraySort);
|
||||
var third_index = t_array[t_array.length >> 1][0];
|
||||
return third_index;
|
||||
}
|
||||
@ -969,7 +970,7 @@ function ArraySort(comparefn) {
|
||||
// It's an interval.
|
||||
var proto_length = indices;
|
||||
for (var i = 0; i < proto_length; i++) {
|
||||
if (!obj.hasOwnProperty(i) && proto.hasOwnProperty(i)) {
|
||||
if (!HAS_OWN_PROPERTY(obj, i) && HAS_OWN_PROPERTY(proto, i)) {
|
||||
obj[i] = proto[i];
|
||||
if (i >= max) { max = i + 1; }
|
||||
}
|
||||
@ -977,8 +978,8 @@ function ArraySort(comparefn) {
|
||||
} else {
|
||||
for (var i = 0; i < indices.length; i++) {
|
||||
var index = indices[i];
|
||||
if (!IS_UNDEFINED(index) &&
|
||||
!obj.hasOwnProperty(index) && proto.hasOwnProperty(index)) {
|
||||
if (!IS_UNDEFINED(index) && !HAS_OWN_PROPERTY(obj, index)
|
||||
&& HAS_OWN_PROPERTY(proto, index)) {
|
||||
obj[index] = proto[index];
|
||||
if (index >= max) { max = index + 1; }
|
||||
}
|
||||
@ -998,7 +999,7 @@ function ArraySort(comparefn) {
|
||||
// It's an interval.
|
||||
var proto_length = indices;
|
||||
for (var i = from; i < proto_length; i++) {
|
||||
if (proto.hasOwnProperty(i)) {
|
||||
if (HAS_OWN_PROPERTY(proto, i)) {
|
||||
obj[i] = UNDEFINED;
|
||||
}
|
||||
}
|
||||
@ -1006,7 +1007,7 @@ function ArraySort(comparefn) {
|
||||
for (var i = 0; i < indices.length; i++) {
|
||||
var index = indices[i];
|
||||
if (!IS_UNDEFINED(index) && from <= index &&
|
||||
proto.hasOwnProperty(index)) {
|
||||
HAS_OWN_PROPERTY(proto, index)) {
|
||||
obj[index] = UNDEFINED;
|
||||
}
|
||||
}
|
||||
@ -1029,14 +1030,14 @@ function ArraySort(comparefn) {
|
||||
}
|
||||
// Maintain the invariant num_holes = the number of holes in the original
|
||||
// array with indices <= first_undefined or > last_defined.
|
||||
if (!obj.hasOwnProperty(first_undefined)) {
|
||||
if (!HAS_OWN_PROPERTY(obj, first_undefined)) {
|
||||
num_holes++;
|
||||
}
|
||||
|
||||
// Find last defined element.
|
||||
while (first_undefined < last_defined &&
|
||||
IS_UNDEFINED(obj[last_defined])) {
|
||||
if (!obj.hasOwnProperty(last_defined)) {
|
||||
if (!HAS_OWN_PROPERTY(obj, last_defined)) {
|
||||
num_holes++;
|
||||
}
|
||||
last_defined--;
|
||||
|
@ -166,6 +166,7 @@ macro TO_STRING_INLINE(arg) = (IS_STRING(%IS_VAR(arg)) ? arg : NonStringToString
|
||||
macro TO_NUMBER_INLINE(arg) = (IS_NUMBER(%IS_VAR(arg)) ? arg : NonNumberToNumber(arg));
|
||||
macro TO_OBJECT_INLINE(arg) = (IS_SPEC_OBJECT(%IS_VAR(arg)) ? arg : ToObject(arg));
|
||||
macro JSON_NUMBER_TO_STRING(arg) = ((%_IsSmi(%IS_VAR(arg)) || arg - arg == 0) ? %_NumberToString(arg) : "null");
|
||||
macro HAS_OWN_PROPERTY(obj, index) = (%_CallFunction(obj, index, ObjectHasOwnProperty));
|
||||
|
||||
# Private names.
|
||||
# GET_PRIVATE should only be used if the property is known to exists on obj
|
||||
|
@ -404,3 +404,47 @@ function cmpTest(a, b) {
|
||||
return a.val - b.val;
|
||||
}
|
||||
arr.sort(cmpTest);
|
||||
|
||||
function TestSortDoesNotDependOnObjectPrototypeHasOwnProperty() {
|
||||
Array.prototype.sort.call({
|
||||
__proto__: { hasOwnProperty: null, 0: 1 },
|
||||
length: 5
|
||||
});
|
||||
|
||||
var arr = new Array(2);
|
||||
Object.defineProperty(arr, 0, { get: function() {}, set: function() {} });
|
||||
arr.hasOwnProperty = null;
|
||||
arr.sort();
|
||||
}
|
||||
|
||||
TestSortDoesNotDependOnObjectPrototypeHasOwnProperty();
|
||||
|
||||
function TestSortDoesNotDependOnArrayPrototypePush() {
|
||||
// InsertionSort is used for arrays which length <= 22
|
||||
var arr = [];
|
||||
for (var i = 0; i < 22; i++) arr[i] = {};
|
||||
Array.prototype.push = function() {
|
||||
fail('Should not call push');
|
||||
};
|
||||
arr.sort();
|
||||
|
||||
// Quicksort is used for arrays which length > 22
|
||||
// Arrays which length > 1000 guarantee GetThirdIndex is executed
|
||||
arr = [];
|
||||
for (var i = 0; i < 2000; ++i) arr[i] = {};
|
||||
arr.sort();
|
||||
}
|
||||
|
||||
TestSortDoesNotDependOnArrayPrototypePush();
|
||||
|
||||
function TestSortDoesNotDependOnArrayPrototypeSort() {
|
||||
var arr = [];
|
||||
for (var i = 0; i < 2000; i++) arr[i] = {};
|
||||
var sortfn = Array.prototype.sort;
|
||||
Array.prototype.sort = function() {
|
||||
fail('Should not call sort');
|
||||
};
|
||||
sortfn.call(arr);
|
||||
}
|
||||
|
||||
TestSortDoesNotDependOnArrayPrototypeSort();
|
||||
|
Loading…
Reference in New Issue
Block a user