Commit 8dfb5c65 authored by ap@webkit.org's avatar ap@webkit.org

Reviewed by Darin.

        <rdar://problem/5908520> REGRESSION (3.1.1-r33033): Crash in WebKit when opening or
        refreshing page on people.com

        The problem was that STL algorithms do not work with non-conformant comparators, and the
        site used sort(function() { return 0.5 - Math.random(); } to randomly shuffle an array.

        https://bugs.webkit.org/show_bug.cgi?id=18687
        REGRESSION(r32220): ecma/Array/15.4.4.5-3.js test now fails in GMT(BST)

        Besides relying on sort stability, this test was just broken, and kept failing with the
        new stable sort.

        Tests: fast/js/sort-randomly.html
               fast/js/sort-stability.html
               fast/js/comparefn-sort-stability.html

        * kjs/avl_tree.h: Added an AVL tree implementation.

        * JavaScriptCore.xcodeproj/project.pbxproj:
        * wtf/AVLTree.h: Added.
        Added an AVL tree implementation.

        * kjs/array_instance.cpp:
        (KJS::ArrayInstance::increaseVectorLength):
        (KJS::ArrayInstance::sort):
        (KJS::AVLTreeAbstractorForArrayCompare::get_less):
        (KJS::AVLTreeAbstractorForArrayCompare::set_less):
        (KJS::AVLTreeAbstractorForArrayCompare::get_greater):
        (KJS::AVLTreeAbstractorForArrayCompare::set_greater):
        (KJS::AVLTreeAbstractorForArrayCompare::get_balance_factor):
        (KJS::AVLTreeAbstractorForArrayCompare::set_balance_factor):
        (KJS::AVLTreeAbstractorForArrayCompare::compare_key_key):
        (KJS::AVLTreeAbstractorForArrayCompare::compare_key_node):
        (KJS::AVLTreeAbstractorForArrayCompare::compare_node_node):
        (KJS::AVLTreeAbstractorForArrayCompare::null):
        (KJS::ArrayInstance::compactForSorting):
        
        * kjs/array_instance.h: increaseVectorLength() now returns a bool to indicate whether it was
        successful.

        * wtf/Vector.h:
        (WTF::Vector::Vector):
        (WTF::::operator=):
        (WTF::::fill):
        Make these methods fail instead instead of crash when allocation fails, matching resize() and
        reserveCapacity(), which already had this behavior. Callers need to check for null buffer
        after making any Vector call that can try to allocate.

        * tests/mozilla/ecma/Array/15.4.4.5-3.js: Fixed the test to use a consistent sort function,
        as suggested in comments to a Mozilla bug filed about it (I'll keep tracking the bug to see
        what the final resolution is).



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@33967 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 48a35d0d
2008-05-21 Alexey Proskuryakov <ap@webkit.org>
Reviewed by Darin.
<rdar://problem/5908520> REGRESSION (3.1.1-r33033): Crash in WebKit when opening or
refreshing page on people.com
The problem was that STL algorithms do not work with non-conformant comparators, and the
site used sort(function() { return 0.5 - Math.random(); } to randomly shuffle an array.
https://bugs.webkit.org/show_bug.cgi?id=18687
REGRESSION(r32220): ecma/Array/15.4.4.5-3.js test now fails in GMT(BST)
Besides relying on sort stability, this test was just broken, and kept failing with the
new stable sort.
Tests: fast/js/sort-randomly.html
fast/js/sort-stability.html
fast/js/comparefn-sort-stability.html
* kjs/avl_tree.h: Added an AVL tree implementation.
* JavaScriptCore.xcodeproj/project.pbxproj:
* wtf/AVLTree.h: Added.
Added an AVL tree implementation.
* kjs/array_instance.cpp:
(KJS::ArrayInstance::increaseVectorLength):
(KJS::ArrayInstance::sort):
(KJS::AVLTreeAbstractorForArrayCompare::get_less):
(KJS::AVLTreeAbstractorForArrayCompare::set_less):
(KJS::AVLTreeAbstractorForArrayCompare::get_greater):
(KJS::AVLTreeAbstractorForArrayCompare::set_greater):
(KJS::AVLTreeAbstractorForArrayCompare::get_balance_factor):
(KJS::AVLTreeAbstractorForArrayCompare::set_balance_factor):
(KJS::AVLTreeAbstractorForArrayCompare::compare_key_key):
(KJS::AVLTreeAbstractorForArrayCompare::compare_key_node):
(KJS::AVLTreeAbstractorForArrayCompare::compare_node_node):
(KJS::AVLTreeAbstractorForArrayCompare::null):
(KJS::ArrayInstance::compactForSorting):
* kjs/array_instance.h: increaseVectorLength() now returns a bool to indicate whether it was
successful.
* wtf/Vector.h:
(WTF::Vector::Vector):
(WTF::::operator=):
(WTF::::fill):
Make these methods fail instead of crash when allocation fails, matching resize() and
reserveCapacity(), which already had this behavior. Callers need to check for null buffer
after making any Vector call that can try to allocate.
* tests/mozilla/ecma/Array/15.4.4.5-3.js: Fixed the test to use a consistent sort function,
as suggested in comments to a Mozilla bug filed about it (I'll keep tracking the bug to see
what the final resolution is).
2008-05-20 Kevin McCullough <kmccullough@apple.com>
Reviewed by Tim.
......
......@@ -203,6 +203,7 @@
E178636D0D9BEEC300D74E75 /* InitializeThreading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */; };
E195679609E7CF1200B89D13 /* UnicodeIcu.h in Headers */ = {isa = PBXBuildFile; fileRef = E195678F09E7CF1200B89D13 /* UnicodeIcu.h */; settings = {ATTRIBUTES = (Private, ); }; };
E195679809E7CF1200B89D13 /* Unicode.h in Headers */ = {isa = PBXBuildFile; fileRef = E195679409E7CF1200B89D13 /* Unicode.h */; settings = {ATTRIBUTES = (Private, ); }; };
E1A596380DE3E1C300C17E37 /* AVLTree.h in Headers */ = {isa = PBXBuildFile; fileRef = E1A596370DE3E1C300C17E37 /* AVLTree.h */; };
E1A862A90D7EBB76001EC6AA /* CollatorICU.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1A862A80D7EBB76001EC6AA /* CollatorICU.cpp */; settings = {COMPILER_FLAGS = "-fno-strict-aliasing"; }; };
E1A862AB0D7EBB7D001EC6AA /* Collator.h in Headers */ = {isa = PBXBuildFile; fileRef = E1A862AA0D7EBB7D001EC6AA /* Collator.h */; settings = {ATTRIBUTES = (Private, ); }; };
E1A862D60D7F2B5C001EC6AA /* CollatorDefault.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1A862D50D7F2B5C001EC6AA /* CollatorDefault.cpp */; };
......@@ -516,6 +517,7 @@
E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InitializeThreading.cpp; sourceTree = "<group>"; };
E195678F09E7CF1200B89D13 /* UnicodeIcu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnicodeIcu.h; sourceTree = "<group>"; };
E195679409E7CF1200B89D13 /* Unicode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Unicode.h; sourceTree = "<group>"; };
E1A596370DE3E1C300C17E37 /* AVLTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AVLTree.h; sourceTree = "<group>"; };
E1A862A80D7EBB76001EC6AA /* CollatorICU.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CollatorICU.cpp; sourceTree = "<group>"; };
E1A862AA0D7EBB7D001EC6AA /* Collator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Collator.h; sourceTree = "<group>"; };
E1A862D50D7F2B5C001EC6AA /* CollatorDefault.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CollatorDefault.cpp; sourceTree = "<group>"; };
......@@ -785,6 +787,7 @@
938C4F690CA06BC700D9310A /* ASCIICType.h */,
65E217B808E7EECC0023E5F6 /* Assertions.cpp */,
65E217B708E7EECC0023E5F6 /* Assertions.h */,
E1A596370DE3E1C300C17E37 /* AVLTree.h */,
5186111D0CC824830081412B /* Deque.h */,
938C4F6B0CA06BCE00D9310A /* DisallowCType.h */,
65E217B908E7EECC0023E5F6 /* FastMalloc.cpp */,
......@@ -1155,6 +1158,7 @@
958D85830DC93230008ABF27 /* StrHash.h in Headers */,
95742F660DD11F5A000917FB /* Profile.h in Headers */,
5DE3D0F50DD8DDFB00468714 /* WebKitAvailability.h in Headers */,
E1A596380DE3E1C300C17E37 /* AVLTree.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
This diff is collapsed.
......@@ -58,7 +58,7 @@ namespace KJS {
bool inlineGetOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
void setLength(unsigned);
void increaseVectorLength(unsigned newLength);
bool increaseVectorLength(unsigned newLength);
unsigned compactForSorting();
......
......@@ -147,7 +147,7 @@ function realsort( x, y ) {
return ( x.valueOf() == y.valueOf() ? 0 : ( x.valueOf() > y.valueOf() ? 1 : -1 ) );
}
function comparefn3( x, y ) {
return ( x == y ? 0 : ( x > y ? 1: -1 ) );
return ( +x == +y ? 0 : ( x > y ? 1 : -1 ) );
}
function clone( source, target ) {
for (i = 0; i < source.length; i++ ) {
......
This diff is collapsed.
......@@ -408,7 +408,8 @@ namespace WTF {
: m_size(size)
, m_buffer(size)
{
TypeOperations::initialize(begin(), end());
if (begin())
TypeOperations::initialize(begin(), end());
}
~Vector()
......@@ -489,7 +490,8 @@ namespace WTF {
: m_size(size)
, m_buffer(size)
{
TypeOperations::uninitializedFill(begin(), end(), val);
if (begin())
TypeOperations::uninitializedFill(begin(), end(), val);
}
void fill(const T&, size_t);
......@@ -519,7 +521,8 @@ namespace WTF {
: m_size(other.size())
, m_buffer(other.capacity())
{
TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
if (begin())
TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
}
template<typename T, size_t inlineCapacity>
......@@ -528,7 +531,8 @@ namespace WTF {
: m_size(other.size())
, m_buffer(other.capacity())
{
TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
if (begin())
TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
}
template<typename T, size_t inlineCapacity>
......@@ -542,6 +546,8 @@ namespace WTF {
else if (other.size() > capacity()) {
clear();
reserveCapacity(other.size());
if (!begin())
return *this;
}
std::copy(other.begin(), other.begin() + size(), begin());
......@@ -563,6 +569,8 @@ namespace WTF {
else if (other.size() > capacity()) {
clear();
reserveCapacity(other.size());
if (!begin())
return *this;
}
std::copy(other.begin(), other.begin() + size(), begin());
......@@ -580,6 +588,8 @@ namespace WTF {
else if (newSize > capacity()) {
clear();
reserveCapacity(newSize);
if (!begin())
return;
}
std::fill(begin(), end(), val);
......
2008-05-21 Alexey Proskuryakov <ap@webkit.org>
Reviewed by Darin.
<rdar://problem/5908520> REGRESSION (3.1.1-r33033): Crash in WebKit when opening or refreshing page on people.com
https://bugs.webkit.org/show_bug.cgi?id=18687
REGRESSION(r32220): ecma/Array/15.4.4.5-3.js test now fails in GMT(BST)
* fast/js/comparefn-sort-stability-expected.txt: Added.
* fast/js/comparefn-sort-stability.html: Added.
* fast/js/resources/comparefn-sort-stability.js: Added.
* fast/js/resources/sort-randomly.js: Added.
* fast/js/resources/sort-stability.js: Added.
* fast/js/sort-randomly-expected.txt: Added.
* fast/js/sort-randomly.html: Added.
* fast/js/sort-stability-expected.txt: Added.
* fast/js/sort-stability.html: Added.
2008-05-21 Alexey Proskuryakov <ap@webkit.org>
Reviewed by Darin.
This tests that sort(compareFn) is a stable sort.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS arr[0] is sortArr[0]
PASS arr[1] is sortArr[2]
PASS arr[2] is sortArr[1]
PASS arr[3] is sortArr[3]
PASS arr[0] is sortArr[0]
PASS arr[1] is sortArr[2]
PASS arr[2] is sortArr[1]
PASS arr[3] is sortArr[3]
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<link rel="stylesheet" href="resources/js-test-style.css">
<script src="resources/js-test-pre.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script src="resources/comparefn-sort-stability.js"></script>
<script src="resources/js-test-post.js"></script>
</body>
</html>
description(
"This tests that sort(compareFn) is a stable sort."
);
function clone(source, target) {
for (i = 0; i < source.length; i++) {
target[i] = source[i];
}
}
var arr = [];
arr[0] = new Number(1);
arr[1] = new Number(2);
arr[2] = new Number(1);
arr[3] = new Number(2);
var sortArr = [];
clone(arr, sortArr);
sortArr.sort(function(a,b) { return a - b; });
shouldBe('arr[0]', 'sortArr[0]');
shouldBe('arr[1]', 'sortArr[2]');
shouldBe('arr[2]', 'sortArr[1]');
shouldBe('arr[3]', 'sortArr[3]');
// Just try again...
sortArr.sort(function(a,b) { return a - b; });
shouldBe('arr[0]', 'sortArr[0]');
shouldBe('arr[1]', 'sortArr[2]');
shouldBe('arr[2]', 'sortArr[1]');
shouldBe('arr[3]', 'sortArr[3]');
var successfullyParsed = true;
description(
"This tests that passing an inconsistent compareFn to sort() doesn't cause a crash."
);
for (var attempt = 0; attempt < 100; ++attempt) {
var arr = [];
for (var i = 0; i < 64; ++i)
arr[i] = i;
arr.sort(function() { return 0.5 - Math.random(); });
}
// Sorting objects that change each time sort() looks at them is the same as using a random compareFn.
function RandomObject() {
this.toString = function() { return (Math.random() * 100).toString(); }
}
for (var attempt = 0; attempt < 100; ++attempt) {
var arr = [];
for (var i = 0; i < 64; ++i)
arr[i] = new RandomObject;
arr.sort();
}
var successfullyParsed = true;
description(
"This tests that sort() is a stable sort."
);
function clone(source, target) {
for (i = 0; i < source.length; i++) {
target[i] = source[i];
}
}
var arr = [];
arr[0] = new Number(1);
arr[1] = new Number(2);
arr[2] = new Number(1);
arr[3] = new Number(2);
var sortArr = [];
clone(arr, sortArr);
sortArr.sort();
shouldBe('arr[0]', 'sortArr[0]');
shouldBe('arr[1]', 'sortArr[2]');
shouldBe('arr[2]', 'sortArr[1]');
shouldBe('arr[3]', 'sortArr[3]');
// Just try again...
sortArr.sort();
shouldBe('arr[0]', 'sortArr[0]');
shouldBe('arr[1]', 'sortArr[2]');
shouldBe('arr[2]', 'sortArr[1]');
shouldBe('arr[3]', 'sortArr[3]');
var successfullyParsed = true;
This tests that passing an inconsistent compareFn to sort() doesn't cause a crash.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<link rel="stylesheet" href="resources/js-test-style.css">
<script src="resources/js-test-pre.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script src="resources/sort-randomly.js"></script>
<script src="resources/js-test-post.js"></script>
</body>
</html>
This tests that sort() is a stable sort.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS arr[0] is sortArr[0]
PASS arr[1] is sortArr[2]
PASS arr[2] is sortArr[1]
PASS arr[3] is sortArr[3]
PASS arr[0] is sortArr[0]
PASS arr[1] is sortArr[2]
PASS arr[2] is sortArr[1]
PASS arr[3] is sortArr[3]
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<link rel="stylesheet" href="resources/js-test-style.css">
<script src="resources/js-test-pre.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script src="resources/sort-stability.js"></script>
<script src="resources/js-test-post.js"></script>
</body>
</html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment