sc/source/core/tool/interpr1.cxx |    4 ++
 sc/source/core/tool/interpr3.cxx |   59 +++++++++++++++++++++------------------
 2 files changed, 37 insertions(+), 26 deletions(-)

New commits:
commit 2d23e19f7991405315bb1ab6a6461cb3e022ca5a
Author:     Eike Rathke <er...@redhat.com>
AuthorDate: Mon Oct 21 19:47:13 2019 +0200
Commit:     Thorsten Behrens <thorsten.behr...@cib.de>
CommitDate: Fri Nov 1 18:10:11 2019 +0100

    Resolves: tdf#127982 SMALL()/LARGE() rank array can be larger than data 
array
    
     This is a combination of 4 commits.
    
    Resolves: tdf#127982 SMALL()/LARGE() rank array can be larger than data 
array
    
    Only set error for the positions where the requested rank is out
    of bounds. This also includes zero or negative rank values,
    instead of setting a global error.
    
    Regression from
    
        commit e22ab5e6f6b0ea49231ca454a567133996306116
        CommitDate: Thu Nov 15 22:12:01 2018 +0100
    
            Resolves: i#32345 Make LARGE()/SMALL() return an array
    
    Where previously due to the iteration in the array case single
    values were returned and assembled.
    
    Reviewed-on: https://gerrit.libreoffice.org/81279
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 475165e431b5392e426db0de4cea50efc2513875)
    
    Related: tdf#127982 In JumpMatrix do not propagate individual errors as 
global
    
    Which for
    https://bugs.documentfoundation.org/attachment.cgi?id=154776
    was the case in sheet1 МультиВПР.E6:E20 even in the to-be-fixed
    SMALL() implementation.
    
    The error is propagated as usual individual matrix element coded
    double error.
    
    Reviewed-on: https://gerrit.libreoffice.org/81252
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 12b54e485103aad4e7dd26423c355b96403b88ba)
    
    -Wimplicit-int-float-conversion
    
    with clang trunk
    
    implicit conversion from 'unsigned long' to 'double' changes value from
    18446744073709551615 to 18446744073709551616
    [-Werror,-Wimplicit-int-float-conversion]
                    if (f < 1.0 || f > std::numeric_limits<SCSIZE>::max())
                                     ~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    Reviewed-on: https://gerrit.libreoffice.org/81319
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>
    (cherry picked from commit 1b0cba8c2cd672b0d5a59a215961c5136a6e656b)
    
    -Werror,-Wimplicit-int-float-conversion
    
    > sc/source/core/tool/interpr3.cxx:3659:36: error: implicit conversion from 
'unsigned long' to 'double' changes value from 18446744073709551615 to 
18446744073709551616 [-Werror,-Wimplicit-int-float-conversion]
    >                 if (f < 1.0 || f > std::numeric_limits<SCSIZE>::max())
    >                                  ~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    since 475165e431b5392e426db0de4cea50efc2513875 "Resolves: tdf#127982
    SMALL()/LARGE() rank array can be larger than data array"
    
    (This supersedes 1b0cba8c2cd672b0d5a59a215961c5136a6e656b
    "-Wimplicit-int-float-conversion", which would have incurred UB if f is 
larger
    than std::numeric_limits<SCSIZE>::max().)
    
    Reviewed-on: https://gerrit.libreoffice.org/81309
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <sberg...@redhat.com>
    (cherry picked from commit f26178b17691ccc9d3da9c25cec9ef08a633b3a7)
    
    Backported:
    As there is no o3tl/float_int_conversion.hxx in 6.3 unfold the
    check to
    
    -                if (f < 1.0 || !o3tl::convertsToAtMost(f, 
std::numeric_limits<SCSIZE>::max()))
    +                if (f < 1.0 || !(f < 
double(std::numeric_limits<SCSIZE>::max()) + 1.0))
    
    5fc6fa3454b354a4017a51a640b96ec80f74f4a4
    ef0eb55ed1ade9fb88f5749774790aebbb27e085
    1eeb75d73169ac89ec4bf9562edcf99d9925f607
    
    Change-Id: Ic992c56cb79e80269cc7200fac5b15cb8aca3566
    Reviewed-on: https://gerrit.libreoffice.org/81346
    Tested-by: Jenkins
    Tested-by: Xisco Faulí <xiscofa...@libreoffice.org>
    Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de>

diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index b94d58cf7b0f..96abd6d9fd18 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -777,6 +777,10 @@ bool ScInterpreter::JumpMatrix( short nStackLevel )
                         }
                         else
                         {
+                            // GetMatrix() does SetErrorInterpreter() at the
+                            // matrix, do not propagate an error from
+                            // matrix->GetValue() as global error.
+                            pMat->SetErrorInterpreter(nullptr);
                             lcl_storeJumpMatResult(pMat.get(), pJumpMatrix, 
nC, nR);
                         }
                         lcl_AdjustJumpMatrix( pJumpMatrix, nCols, nRows );
diff --git a/sc/source/core/tool/interpr3.cxx b/sc/source/core/tool/interpr3.cxx
index 85eb4b7167a4..414237b369b3 100644
--- a/sc/source/core/tool/interpr3.cxx
+++ b/sc/source/core/tool/interpr3.cxx
@@ -3642,48 +3642,50 @@ void ScInterpreter::CalculateSmallLarge(bool bSmall)
 
     SCSIZE nCol = 0, nRow = 0;
     auto aArray = GetTopNumberArray(nCol, nRow);
-    auto aArraySize = aArray.size();
-    if (aArraySize == 0 || nGlobalError != FormulaError::NONE)
+    const auto nRankArraySize = aArray.size();
+    if (nRankArraySize == 0 || nGlobalError != FormulaError::NONE)
     {
         PushNoValue();
         return;
     }
-    assert(aArraySize == nCol * nRow);
-    for (double fArg : aArray)
-    {
-        double f = ::rtl::math::approxFloor(fArg);
-        if (f < 1.0)
-        {
-            PushIllegalArgument();
-            return;
-        }
-    }
+    assert(nRankArraySize == nCol * nRow);
 
     std::vector<SCSIZE> aRankArray;
-    aRankArray.reserve(aArraySize);
+    aRankArray.reserve(nRankArraySize);
     std::transform(aArray.begin(), aArray.end(), 
std::back_inserter(aRankArray),
-                   [](double f) { return static_cast<SCSIZE>(f); });
-
-    auto itMaxRank = std::max_element(aRankArray.begin(), aRankArray.end());
-    assert(itMaxRank != aRankArray.end());
-    SCSIZE k = *itMaxRank;
+            [](double f) {
+                f = rtl::math::approxFloor(f);
+                // Valid ranks are >= 1.
+                if (f < 1.0 || !(f < 
double(std::numeric_limits<SCSIZE>::max()) + 1.0))
+                    return static_cast<SCSIZE>(0);
+                return static_cast<SCSIZE>(f);
+            });
 
     vector<double> aSortArray;
     GetNumberSequenceArray(1, aSortArray, false );
-    SCSIZE nSize = aSortArray.size();
-    if (nSize == 0 || nGlobalError != FormulaError::NONE || nSize < k)
+    const SCSIZE nSize = aSortArray.size();
+    if (nSize == 0 || nGlobalError != FormulaError::NONE)
         PushNoValue();
-    else if (aArraySize == 1)
+    else if (nRankArraySize == 1)
     {
-        vector<double>::iterator iPos = aSortArray.begin() + (bSmall ? k-1 : 
nSize-k);
-        ::std::nth_element( aSortArray.begin(), iPos, aSortArray.end());
-        PushDouble( *iPos);
+        const SCSIZE k = aRankArray[0];
+        if (k < 1 || nSize < k)
+            PushNoValue();
+        else
+        {
+            vector<double>::iterator iPos = aSortArray.begin() + (bSmall ? k-1 
: nSize-k);
+            ::std::nth_element( aSortArray.begin(), iPos, aSortArray.end());
+            PushDouble( *iPos);
+        }
     }
     else
     {
         std::set<SCSIZE> aIndices;
         for (SCSIZE n : aRankArray)
-            aIndices.insert(bSmall ? n-1 : nSize-n);
+        {
+            if (1 <= n && n <= nSize)
+                aIndices.insert(bSmall ? n-1 : nSize-n);
+        }
         // We can spare sorting when the total number of ranks is small enough.
         // Find only the elements at given indices if, arbitrarily, the index 
size is
         // smaller than 1/3 of the haystack array's size; just sort it 
squarely, otherwise.
@@ -3702,7 +3704,12 @@ void ScInterpreter::CalculateSmallLarge(bool bSmall)
 
         aArray.clear();
         for (SCSIZE n : aRankArray)
-            aArray.push_back(aSortArray[bSmall ? n-1 : nSize-n]);
+        {
+            if (1 <= n && n <= nSize)
+                aArray.push_back( aSortArray[bSmall ? n-1 : nSize-n]);
+            else
+                aArray.push_back( CreateDoubleError( FormulaError::NoValue));
+        }
         ScMatrixRef pResult = GetNewMat(nCol, nRow, aArray);
         PushMatrix(pResult);
     }
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to