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

Reply via email to