diff options
author | Ulf Hermann <[email protected]> | 2023-07-11 11:16:43 +0200 |
---|---|---|
committer | Ulf Hermann <[email protected]> | 2023-07-25 14:33:15 +0200 |
commit | f0b2fbcf47f00071a7f5f1a04258d451badcb81a (patch) | |
tree | c119291139026217804b8533fbfbec509cba8445 /src/qml/jsruntime/qv4arraydata.cpp | |
parent | 1c01b3cc8a820df4d55ab6fcfcfe2b92e81270be (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.cpp | 32 |
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(); |