extraction on implicit list fixed. 03/21603/5
Cedric Delamarre [Thu, 22 Oct 2020 12:23:14 +0000 (14:23 +0200)]
   https://bugzilla.scilab.org/show_bug.cgi?id=16141
   https://bugzilla.scilab.org/show_bug.cgi?id=16396

   test_run("ast", ["bug_16396" "bug_16141" "extract"])

Change-Id: I2c63e1c27f93727dba4eeb24a625ee384a91a44d

scilab/CHANGES.md
scilab/modules/ast/includes/types/implicitlist.hxx
scilab/modules/ast/src/cpp/types/arrayof.cpp
scilab/modules/ast/src/cpp/types/implicitlist.cpp
scilab/modules/ast/src/cpp/types/types_tools.cpp
scilab/modules/ast/tests/nonreg_tests/bug_16141.tst [new file with mode: 0644]
scilab/modules/ast/tests/nonreg_tests/bug_16396.tst [new file with mode: 0644]
scilab/modules/ast/tests/unit_tests/extract.tst [new file with mode: 0644]

index 34e4bd7..c62a8d8 100644 (file)
@@ -300,6 +300,7 @@ Bug Fixes
 * [#16069](https://bugzilla.scilab.org/16069): [].figure_name crashes Scilab.
 * [#16106](https://bugzilla.scilab.org/16106): Xcos sciblk4 user-defined blocks did not handle opar and odstate/oz correctly.
 * [#16122](https://bugzilla.scilab.org/16122): concat polynomials with <> var did not raise an error.
+* [#16141](https://bugzilla.scilab.org/16141): recursive extraction `(m:n)($)` crashed Scilab
 * [#16151](https://bugzilla.scilab.org/16151): `isequal(1:$, 2:$)` returned `%T`.
 * [#16193](https://bugzilla.scilab.org/16193): `covStart()` clear previous coverage information. `profileEnable()` could be use to append a macro later on.
 * [#16196](https://bugzilla.scilab.org/16196): `covStart()` help page was incomplete about the API usage.
@@ -316,6 +317,7 @@ Bug Fixes
 * [#16370](https://bugzilla.scilab.org/16370): `msprintf()` did not handle LaTeX dollars anymore.
 * [#16374](https://bugzilla.scilab.org/16374): Any plot with datatips saved in Scilab 5.5 could not be loaded in Scilab 6.
 * [#16391](https://bugzilla.scilab.org/16391): `csvRead()` was crashing with CSV files containing empty lines.
+* [#16396](https://bugzilla.scilab.org/16396): recursive extraction `(m:n)(:)` crashed Scilab
 * [#16397](https://bugzilla.scilab.org/16397): display of long (real) column vectors was slow (regression).
 * [#16399](https://bugzilla.scilab.org/16399): `mtlb_zeros([])` was crashing Scilab.
 * [#16401](https://bugzilla.scilab.org/16401): global `external_object_java` class was crashing Scilab.
index 5f2c0f1..69f77d0 100644 (file)
@@ -124,7 +124,7 @@ public :
     }
 
     //extract single value in a InternalType
-    void extractValue(int _iOccur, InternalType*); //Single value
+    bool extractValue(int _iOccur, InternalType*); //Single value
     void extractValueAsDouble(int _iOccur, Double*);
     template<typename T>
     void extractValueAsInteger(int _iOccur, T* val);
index 24d0474..7df4a81 100644 (file)
@@ -1413,6 +1413,10 @@ GenericType* ArrayOf<T>::extract(typed_list* _pArgs)
 
                 //free pArg content
                 cleanIndexesArguments(_pArgs, &pArg);
+                if(pOut)
+                {
+                    pOut->killMe();
+                }
                 return NULL;
             }
         }
index 42ca980..b1f74a0 100644 (file)
@@ -467,14 +467,9 @@ InternalType* ImplicitList::getInitalType()
 }
 
 //extract single value in a InternalType
-void ImplicitList::extractValue(int _iOccur, InternalType* pIT)
+bool ImplicitList::extractValue(int _iOccur, InternalType* pIT)
 {
-    if (pIT == nullptr)
-    {
-        return;
-    }
-
-    if (compute())
+    if (pIT && compute() && m_iSize >= _iOccur)
     {
         switch (m_eOutType)
         {
@@ -506,7 +501,10 @@ void ImplicitList::extractValue(int _iOccur, InternalType* pIT)
                 extractValueAsDouble(_iOccur, pIT->getAs<Double>());
                 break;
         }
+        return true;
     }
+
+    return false;
 }
 
 //extract matrix in a Internaltype
@@ -652,7 +650,6 @@ InternalType* ImplicitList::extract(typed_list* _pArgs)
     int iDims = (int)_pArgs->size();
     typed_list pArg;
     InternalType* pOut = NULL;
-    int index = 0;
 
     int* piMaxDim = new int[iDims];
     int* piCountDim = new int[iDims];
@@ -663,59 +660,126 @@ InternalType* ImplicitList::extract(typed_list* _pArgs)
     {
         //free pArg content
         cleanIndexesArguments(_pArgs, &pArg);
+        delete[] piMaxDim;
+        delete[] piCountDim;
         return createEmptyDouble();
     }
 
-    if (iDims == 1 && iSeqCount == 1)
+    // computable
+    if(compute())
     {
-        if (piMaxDim[0] > 0 && piMaxDim[0] <= 3)
+        if(iSeqCount == 1 && iDims == 1) // (0:9)(5)
         {
-            //standard case a(1)
-            Double* pDbl = pArg[0]->getAs<Double>();
-            index = (int)pDbl->get()[0] - 1;
+            int index = (int)pArg[0]->getAs<Double>()->get()[0] - 1;
+            if(index < m_iSize)
+            {
+                pOut = getInitalType();
+                if(extractValue(index, pOut) == false)
+                {
+                    pOut->killMe();
+                    pOut = NULL;
+                }
+            }
         }
         else
         {
-            index = 0;
+            // for more complex argument, expand the implicit list
+            // to perform the extraction on a more common type.
+            InternalType* pIT = extractFullMatrix();
+            pOut = pIT->getAs<GenericType>()->extract(_pArgs);
+            pIT->killMe();
         }
     }
-    else
+    else if((piMaxDim[0] > 0 && piMaxDim[0] <= 3) && iSeqCount != -1)
     {
-        int* piDims = new int[iDims];
-        int* pIndex = new int[iDims];
-        for (int i = 0 ; i < iDims ; i++)
+        // check dims indexes other than the first one
+        // (1:$)(2,1) works but not (1:$)(1,2)
+        bool bOk = true;
+        for(int i = 1; i < iDims; i++)
         {
-            piDims[i] = 1;
+            if(pArg[i]->getAs<Double>()->get(0) != 1)
+            {
+                bOk = false;
+                break;
+            }
         }
 
-        for (int i = 0 ; i < iSeqCount ; i++)
+        if(bOk)
         {
-            for (int j = 0 ; j < iDims ; j++)
+            std::vector<int> indexes;
+            indexes.reserve(iSeqCount);
+            bool isOutPoly = false;
+            double* pDbl = pArg[0]->getAs<Double>()->get();
+            for (int i = 0 ; i < iSeqCount ; i++)
             {
-                Double* pDbl = pArg[j]->getAs<Double>();
-                pIndex[j] = (int)pDbl->get()[i] - 1;
+                indexes.push_back((int)pDbl[i] - 1);
             }
 
-            index = getIndexWithDims(pIndex, piDims, iDims);
+            std::vector<InternalType*> vect;
+            for (int i = 0 ; i < iSeqCount ; i++)
+            {
+                switch (indexes[i])
+                {
+                    case 0 : // start
+                        vect.push_back(getStart());
+                        // pPoly->set(i, start);
+                        break;
+                    case 1 : // step
+                        vect.push_back(getStep());
+                        break;
+                    case 2 : // end
+                        vect.push_back(getEnd());
+                        break;
+                    default :
+                        vect.clear();
+                        break;
+                }
+            }
+
+            Polynom* pPoly = nullptr;
+            for(auto elem : vect)
+            {
+                if(elem->isPoly())
+                {
+                    // (0:$)(:) vs (0:$)(1:$)
+                    int iRows = (*_pArgs)[0]->isColon() ? iSeqCount : 1;
+                    int iCols = (*_pArgs)[0]->isColon() ? 1 : iSeqCount;
+                    pPoly = new Polynom(L"$", iRows, iCols);
+                    break;
+                }
+            }
+
+            if(pPoly)
+            {
+                for (int i = 0 ; i < iSeqCount ; i++)
+                {
+                    if(vect[i]->isPoly())
+                    {
+                        pPoly->set(i, vect[i]->getAs<Polynom>()->get(0));
+                    }
+                    else
+                    {
+                        double* coef = nullptr;
+                        SinglePoly* singlePoly = new SinglePoly(&coef, 0);
+                        coef[0] = vect[i]->getAs<Double>()->get(0);
+                        pPoly->set(i, singlePoly);
+                        singlePoly->killMe();
+                    }
+                }
+
+                pOut = pPoly;
+            }
+            else if(vect.empty() == false)
+            {
+                Double* pDbl = new Double(1, iSeqCount);
+                for (int i = 0 ; i < iSeqCount ; i++)
+                {
+                    pDbl->set(i, vect[i]->getAs<Double>()->get(0));
+                }
+
+                pOut = pDbl;
+            }
         }
-        delete[] pIndex;
-        delete[] piDims;
-    }
-
-    switch (index)
-    {
-        case 0 :
-            pOut = getStart();
-            break;
-        case 1 :
-            pOut = getStep();
-            break;
-        case 2 :
-            pOut = getEnd();
-            break;
-        default :
-            pOut = NULL;
-            break;
     }
 
     //free pArg content
index 8482336..56576fc 100644 (file)
@@ -574,7 +574,17 @@ int checkIndexesArguments(InternalType* _pRef, typed_list* _pArgsIn, typed_list*
                 else
                 {
                     //evalute polynom with "MaxDim"
-                    int iMaxDim = _pRef->getAs<GenericType>()->getVarMaxDim(i, iDims);
+                    int iMaxDim = 0;
+                    if(_pRef->isImplicitList())
+                    {
+                        ImplicitList* pIL = _pRef->getAs<ImplicitList>();
+                        iMaxDim = pIL->compute() ? pIL->getSize() : 3;
+                    }
+                    else
+                    {
+                        iMaxDim = _pRef->getAs<GenericType>()->getVarMaxDim(i, iDims);
+                    }
+
 #if defined(_SCILAB_DEBUGREF_)
                     Double* pdbl = new Double(iMaxDim);
 #else
@@ -687,10 +697,16 @@ int checkIndexesArguments(InternalType* _pRef, typed_list* _pArgsIn, typed_list*
             Polynom* pMP = pIT->getAs<types::Polynom>();
             int iMaxDim = 0;
             //if pRef == NULL, use 0 insteadof, to allow a($+1) on new variable
-            if (_pRef)
+            if (_pRef && _pRef->isGenericType())
             {
                 iMaxDim = _pRef->getAs<GenericType>()->getVarMaxDim(i, iDims);
             }
+            else if(_pRef && _pRef->isImplicitList())
+            {
+                ImplicitList* pIL = _pRef->getAs<ImplicitList>();
+                // pIL is not computable, iMaxDim = 3 is the implicit list end.
+                iMaxDim = pIL->compute() ? pIL->getSize() : 3;
+            }
 
 #ifdef _SCILAB_DEBUGREF_
             Double* pdbl = new Double(iMaxDim); // $
diff --git a/scilab/modules/ast/tests/nonreg_tests/bug_16141.tst b/scilab/modules/ast/tests/nonreg_tests/bug_16141.tst
new file mode 100644 (file)
index 0000000..8ebf0dc
--- /dev/null
@@ -0,0 +1,20 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2020 - Cedric Delamarre
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+//
+// <-- Non-regression test for bug 16141 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/16141
+//
+// <-- Short Description -->
+// extraction on implicit list crashes Scilab
+
+assert_checkequal((3:17)($), 17);
+assert_checkequal((3:17)($-3:$), 14:17);
\ No newline at end of file
diff --git a/scilab/modules/ast/tests/nonreg_tests/bug_16396.tst b/scilab/modules/ast/tests/nonreg_tests/bug_16396.tst
new file mode 100644 (file)
index 0000000..de71b87
--- /dev/null
@@ -0,0 +1,24 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2020 - Cedric Delamarre
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+//
+// <-- Non-regression test for bug 16396 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/16396
+//
+// <-- Short Description -->
+// array extraction with : crash the software
+
+computed = 1:10;
+assert_checkequal(((1:10))(1), computed(1));
+assert_checkequal(((1:10))(1:10), computed);
+assert_checkequal(((1:10)')(1:10), computed');
+assert_checkequal(((1:10))(:), computed');
+assert_checkequal((1:10)(:), computed');
\ No newline at end of file
diff --git a/scilab/modules/ast/tests/unit_tests/extract.tst b/scilab/modules/ast/tests/unit_tests/extract.tst
new file mode 100644 (file)
index 0000000..8574e77
--- /dev/null
@@ -0,0 +1,54 @@
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2020 - ESI Group - Cedric Delamarre
+//
+// This file is hereby licensed under the terms of the GNU GPL v2.0,
+// pursuant to article 5.3.4 of the CeCILL v.2.1.
+// This file was originally licensed under the terms of the CeCILL v2.1,
+// and continues to be available under such terms.
+// For more information, see the COPYING file which you should have received
+// along with this program.
+//
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+//
+
+//---------------------------//
+// Implicit list extraction  //
+//---------------------------//
+
+invalid_index = msprintf(_("Invalid index.\n"));
+
+result = 0:9;
+assert_checkequal((0:9)(1), result(1));
+assert_checkequal((0:9)(2), result(2));
+assert_checkequal((0:9)(3), result(3));
+assert_checkequal((0:9)(4), result(4));
+assert_checkequal((0:9)($), result($));
+assert_checkerror("(0:9)($+1)", invalid_index);
+assert_checkerror("(0:9)($+1,$)", invalid_index);
+assert_checkerror("(0:9)($-1,$)", invalid_index);
+assert_checkequal((0:9)($-1), result($-1));
+assert_checkerror("(0:9)(42)", invalid_index);
+assert_checkequal((0:9)(:), result(:));
+assert_checkequal((0:9)(1:$), result(1:$));
+assert_checkequal((0:9)($:-1:1), result($:-1:1));
+assert_checkequal((0:9)([1,2,2,1]), result([1, 2, 2, 1]));
+assert_checkerror("(0:9)(1,2,2,1)", invalid_index);
+assert_checkequal((0:9)(1,1), result(1,1));
+
+assert_checkequal((0:$)(1), 0);
+assert_checkequal((0:$)(2), 1);
+assert_checkequal((0:$)(3), $);
+assert_checkerror("(0:$)(4)", invalid_index);
+assert_checkequal((0:$)($), $);
+assert_checkerror("(0:$)($+1)", invalid_index);
+assert_checkerror("(0:$)($+1,$)", invalid_index);
+assert_checkerror("(0:$)($-1,$)", invalid_index);
+assert_checkequal((0:$)($-1), 1);
+assert_checkerror("(0:$)(42)", invalid_index);
+assert_checkequal((0:$)(:), [0; 1; $]);
+assert_checkequal((0:$)(1:$), [0, 1, $]);
+assert_checkequal((0:$)($:-1:1), [$, 1, 0]);
+assert_checkequal((0:$)([1,2,2,1]), [0, 1, 1, 0]);
+assert_checkerror("(0:$)(1,2,2,1)", invalid_index);
+assert_checkequal((0:$)(1,1), 0);
\ No newline at end of file