sc/source/core/data/dociter.cxx | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
New commits: commit 78a66f99958ed258686cb2fac90f361954b5afe4 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Thu Mar 20 00:41:00 2025 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Thu Mar 20 06:10:04 2025 +0100 tdf#165821: don't change range of ScCellIterator outside of wanted bounds Commit 8e3a29110c8ad739bedeea90932663608d8d3935 (ofz#20904 check bounds, 2020-02-29) workarounded an out-of-bounds access, by changing maStartPos to be in the allocated range. But that meant that functions that wanted the data from some specific range, got the data from another. Fix this by looking for table in the wanted range that has the allocated columns in the wanted range (cf. to ScCellIterator::getCurrent(), which skips the unallocated area altogether). If no tables have such columns, just initialize maCurPos with an unvalid table, which causes first() to return false (the same as with invalid tables). No idea how to make a unit test for this. Adding a formula like =COUNTA(ABC:ABC) to the end of sc/qa/unit/data/functions/statistical/fods/counta.fods, with expected value of 0, doesn't fail without the fix. Change-Id: I570cf4a11a410b4e79eb4df785d6c52897973b6e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183141 Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Tested-by: Jenkins diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx index 00309ceb871b..6b90faf2b06e 100644 --- a/sc/source/core/data/dociter.cxx +++ b/sc/source/core/data/dociter.cxx @@ -875,17 +875,29 @@ void ScCellIterator::init() while (maEndPos.Tab() > 0 && !mrDoc.maTabs[maEndPos.Tab()]) maEndPos.IncTab(-1); // Only the tables in use - if (maStartPos.Tab() > maEndPos.Tab()) - maStartPos.SetTab(maEndPos.Tab()); - - if (!mrDoc.maTabs[maStartPos.Tab()]) + if (maStartPos.Tab() > maEndPos.Tab() || !mrDoc.maTabs[maStartPos.Tab()]) { assert(!"Table not found"); - maStartPos = ScAddress(mrDoc.MaxCol()+1, mrDoc.MaxRow()+1, MAXTAB+1); // -> Abort on GetFirst. + maStartPos = ScAddress(mrDoc.MaxCol()+1, mrDoc.MaxRow()+1, MAXTAB+1); // -> Abort on first(). } else { - maStartPos.SetCol(mrDoc.maTabs[maStartPos.Tab()]->ClampToAllocatedColumns(maStartPos.Col())); + for (auto tabNo = maStartPos.Tab();; ++tabNo) + { + const auto& pTab = mrDoc.maTabs[tabNo]; + if (pTab && maStartPos.Col() < pTab->GetAllocatedColumnsCount()) + { + // Found the first table with allocated columns in range + maStartPos.SetTab(tabNo); + break; + } + if (tabNo == maEndPos.Tab()) + { + // No allocated columns found in the range -> return false from first(). + maStartPos = ScAddress(mrDoc.MaxCol() + 1, mrDoc.MaxRow() + 1, MAXTAB + 1); + break; + } + } } maCurPos = maStartPos;