return p1s->toQString() < p2s->toQString();
}
+template <typename RandomAccessIterator, typename T, typename LessThan>
+void sortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan)
+{
+top:
+ int span = int(end - start);
+ if (span < 2)
+ return;
+
+ --end;
+ RandomAccessIterator low = start, high = end - 1;
+ RandomAccessIterator pivot = start + span / 2;
+
+ if (lessThan(*end, *start))
+ qSwap(*end, *start);
+ if (span == 2)
+ return;
+
+ if (lessThan(*pivot, *start))
+ qSwap(*pivot, *start);
+ if (lessThan(*end, *pivot))
+ qSwap(*end, *pivot);
+ if (span == 3)
+ return;
+
+ qSwap(*pivot, *end);
+
+ while (low < high) {
+ while (low < high && lessThan(*low, *end))
+ ++low;
+
+ while (high > low && lessThan(*end, *high))
+ --high;
+
+ if (low < high) {
+ qSwap(*low, *high);
+ ++low;
+ --high;
+ } else {
+ break;
+ }
+ }
+
+ if (lessThan(*low, *end))
+ ++low;
+
+ qSwap(*end, *low);
+ sortHelper(start, low, t, lessThan);
+
+ start = low + 1;
+ ++end;
+ goto top;
+}
+
+
void ArrayData::sort(ExecutionContext *context, ObjectRef thisObject, const ValueRef comparefn, uint len)
{
if (!len)
ArrayElementLessThan lessThan(context, thisObject, comparefn);
Value *begin = thisObject->arrayData->data;
- std::sort(begin, begin + len, lessThan);
+ sortHelper(begin, begin + len, *begin, lessThan);
#ifdef CHECK_SPARSE_ARRAYS
thisObject->initSparseArray();
void reentrancy_objectCreation();
void jsIncDecNonObjectProperty();
void JSONparse();
+ void arraySort();
void qRegExpInport_data();
void qRegExpInport();
QVERIFY(ret.isObject());
}
+void tst_QJSEngine::arraySort()
+{
+ // tests that calling Array.sort with a bad sort function doesn't cause issues
+ // Using std::sort is e.g. not safe when used with a bad sort function and causes
+ // crashes
+ QJSEngine eng;
+ eng.evaluate("function crashMe() {"
+ " var data = [];"
+ " for (var i = 0; i < 50; i++) {"
+ " data[i] = 'whatever';"
+ " }"
+ " data.sort(function(a, b) {"
+ " return -1;"
+ " });"
+ "}"
+ "crashMe();");
+}
+
static QRegExp minimal(QRegExp r) { r.setMinimal(true); return r; }
void tst_QJSEngine::qRegExpInport_data()