aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4arraydata.cpp
diff options
context:
space:
mode:
authorUlf Hermann <[email protected]>2023-07-11 11:16:43 +0200
committerUlf Hermann <[email protected]>2023-07-25 14:33:15 +0200
commitf0b2fbcf47f00071a7f5f1a04258d451badcb81a (patch)
treec119291139026217804b8533fbfbec509cba8445 /src/qml/jsruntime/qv4arraydata.cpp
parent1c01b3cc8a820df4d55ab6fcfcfe2b92e81270be (diff)
QV4::ArrayData: Fix offset calculation for sort()
We cannot just sort the raw values. We have to take the offset into account. If the array wraps around the end of the allocation, we have to move it around to be contiguous. Pick-to: 6.6 6.5 6.2 5.15 Fixes: QTBUG-58718 Change-Id: I1866b3f271d97352e250d687955af3fc54340334 Reviewed-by: Fabian Kosmale <[email protected]> Reviewed-by: Sami Shalayel <[email protected]> Reviewed-by: Qt CI Bot <[email protected]>
Diffstat (limited to 'src/qml/jsruntime/qv4arraydata.cpp')
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp32
1 files changed, 30 insertions, 2 deletions
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index 6e01c50048..e1da807c21 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -711,8 +711,36 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
ArrayElementLessThan lessThan(engine, comparefn);
- Value *begin = thisObject->arrayData()->values.values;
- sortHelper(begin, begin + len, lessThan);
+ const auto thisArrayData = thisObject->arrayData();
+ uint startIndex = thisArrayData->mappedIndex(0);
+ uint endIndex = thisArrayData->mappedIndex(len - 1) + 1;
+ if (startIndex < endIndex) {
+ // Values are contiguous. Sort right away.
+ sortHelper(
+ thisArrayData->values.values + startIndex,
+ thisArrayData->values.values + endIndex,
+ lessThan);
+ } else {
+ // Values wrap around the end of the allocation. Close the gap to form a contiguous array.
+ // We're going to sort anyway. So we don't need to care about order.
+
+ // ArrayElementLessThan sorts empty and undefined to the end of the array anyway, but we
+ // probably shouldn't rely on the unused slots to be actually undefined or empty.
+
+ const uint gap = startIndex - endIndex;
+ const uint allocEnd = thisArrayData->values.alloc - 1;
+ for (uint i = 0; i < gap; ++i) {
+ const uint from = allocEnd - i;
+ const uint to = endIndex + i;
+ if (from < startIndex)
+ break;
+
+ std::swap(thisArrayData->values.values[from], thisArrayData->values.values[to]);
+ }
+
+ thisArrayData->offset = 0;
+ sortHelper(thisArrayData->values.values, thisArrayData->values.values + len, lessThan);
+ }
#ifdef CHECK_SPARSE_ARRAYS
thisObject->initSparseArray();