sc/source/core/data/queryiter.cxx | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-)
New commits: commit 43e9582e01b63fb55a0e8cdea7b7f3bb209886ee Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Tue Mar 7 10:48:30 2023 +0000 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Mon Mar 13 09:18:23 2023 +0000 crashtesting: assert on loading forum-mso-en4-144513.xls the same case, though non-fatal in that instance, can be seen with sc/qa/unit/data/functions/spreadsheet/fods/hlookup.fods with a maParam.nCol2 of 27, nFoundCol of 23, nCol of 28 so a nColDiff of 5. rParam.nField was originally reduced from 27 to 22 with -= nColDiff, while with this approach of restoring the original position it is restored to the value of 23 it had before the last call to GetNext() Change-Id: Ia6ca73be03fe313c81a23f176a40a5e619a75d3e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148415 Tested-by: Caolán McNamara <caol...@redhat.com> Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/sc/source/core/data/queryiter.cxx b/sc/source/core/data/queryiter.cxx index 35e8e2a85169..7fef5381750e 100644 --- a/sc/source/core/data/queryiter.cxx +++ b/sc/source/core/data/queryiter.cxx @@ -702,11 +702,28 @@ bool ScQueryCellIterator< accessType >::FindEqualOrSortedLastInRange( SCCOL& nFo // First equal entry or last smaller than (greater than) entry. PositionType aPosSave; bool bNext = false; + SCSIZE nEntries = maParam.GetEntryCount(); + std::vector<SCCOL> aFoundFieldPositions(nEntries); do { nFoundCol = GetCol(); nFoundRow = GetRow(); aPosSave = maCurPos; + // If we might need to rewind below, save the position to rewind to + // rather than calculate it as a diff between nCol and nFoundCol as + // PerformQuery can return early if nCol is greater than + // maParam.nCol2 or AllocatedColumns + if (maParam.mbRangeLookup && bAdvanceQuery) + { + for (SCSIZE j=0; j < nEntries; ++j) + { + ScQueryEntry& rEntry = maParam.GetEntry( j ); + if (rEntry.bDoQuery) + aFoundFieldPositions[j] = maParam.GetEntry(j).nField; + else + break; // for + } + } if (IsEqualConditionFulfilled()) break; bNext = GetNext(); @@ -719,7 +736,7 @@ bool ScQueryCellIterator< accessType >::FindEqualOrSortedLastInRange( SCCOL& nFo { // Step back to last in range and adjust position markers for // GetNumberFormat() or similar. - SCCOL nColDiff = nCol - nFoundCol; + bool bColDiff = nCol != nFoundCol; nCol = nFoundCol; nRow = nFoundRow; maCurPos = aPosSave; @@ -730,20 +747,15 @@ bool ScQueryCellIterator< accessType >::FindEqualOrSortedLastInRange( SCCOL& nFo // if query is ByString and vice versa. maParam.mbRangeLookup = false; // Step back the last field advance if GetNext() did one. - if (bAdvanceQuery && nColDiff) + if (bAdvanceQuery && bColDiff) { - SCSIZE nEntries = maParam.GetEntryCount(); for (SCSIZE j=0; j < nEntries; ++j) { ScQueryEntry& rEntry = maParam.GetEntry( j ); if (rEntry.bDoQuery) { - if (rEntry.nField - nColDiff >= 0) - rEntry.nField -= nColDiff; - else - { - assert(!"FindEqualOrSortedLastInRange: rEntry.nField -= nColDiff < 0"); - } + rEntry.nField = aFoundFieldPositions[j]; + assert(rEntry.nField >= 0); } else break; // for