* Bug #14030 fixed - schur fixed about bad delete and error management. 65/17265/7
Cedric Delamarre [Mon, 28 Sep 2015 15:21:19 +0000 (17:21 +0200)]
Scilab also crashed with fft(a, -1) instruction (free NULL pointer)
To test : Demo > Introduction: Getting started with Scilab > Linear
Algebra

Change-Id: Id2bb46551ead178dbe2b5f60c437217adcc1c962

scilab/CHANGES_6.0.X
scilab/modules/fftw/src/c/fftw_utilities.c
scilab/modules/linear_algebra/src/cpp/scischur.cpp
scilab/modules/linear_algebra/tests/nonreg_tests/bug_14030.dia.ref [new file with mode: 0644]
scilab/modules/linear_algebra/tests/nonreg_tests/bug_14030.tst [new file with mode: 0644]

index e86d7a8..3b14eb8 100644 (file)
@@ -195,6 +195,8 @@ Bug Fixes
 
 * Bug #14028 fixed - force flag of genlib did not rebuild bin file.
 
+* Bug #14030 fixed - Linear algebra demo crashed due to a bad delete in schur implementation and free a NULL pointer in fft implementation. 
+
 * Bug #14036 fixed - tag and user_data properties were not displayed and not documented for light entity.
 
 * Bug #14038 fixed - Encoded integers were no longer accepted for list extraction.
index acf3181..76dd8b3 100644 (file)
@@ -1336,7 +1336,6 @@ int complete_array(double *Ar, double *Ai, guru_dim_struct gdim)
 int withMKL(void)
 {
     static int iWithMKL = -1;
-
     if (iWithMKL == -1)
     {
         char* str = NULL;
index e0de151..02b2da0 100644 (file)
@@ -19,6 +19,7 @@
 #include "double.hxx"
 #include "bool.hxx"
 #include "function.hxx"
+#include "commentexp.hxx"
 
 extern "C"
 {
@@ -30,7 +31,7 @@ int schur_sb02mw(double* _real, double* _img)
 {
     return dpythags(*_real, *_img) < 1 ? 1 : 0;
 }
-int schur_sb02mv(double* _real, double* _img)
+int schur_sb02mv(double* _real, double* /*_img*/)
 {
     /* original Fortran code does not use _img aka IEIG (SB02MV = REIG.LT.ZERO) */
     return *_real < 0 ? 1 : 0;
@@ -38,61 +39,73 @@ int schur_sb02mv(double* _real, double* _img)
 int schur_dgees(double* _real, double* _img)
 {
     types::Callable* pCall = ConfigVariable::getSchurFunction();
+    if (pCall == NULL)
+    {
+        return 0;
+    }
+
+    char errorMsg[256];
     int iRet = 0;
 
-    if (pCall)
-    {
-        types::typed_list in;
-        types::typed_list out;
-        types::optional_list opt;
-        int iRetCount = 1;
+    types::typed_list in;
+    types::typed_list out;
+    types::optional_list opt;
+    int iRetCount = 1;
 
-        types::Double* pDbl = new types::Double(*_real, *_img);
-        pDbl->IncreaseRef();
-        in.push_back(pDbl);
+    types::Double* pDbl = new types::Double(*_real, *_img);
+    pDbl->IncreaseRef();
+    in.push_back(pDbl);
 
-        bool bOk = pCall->call(in, opt, iRetCount, out) == types::Function::OK;
+    try
+    {
+        // new std::wstring(L"") is delete in destructor of ast::CommentExp
+        pCall->invoke(in, opt, iRetCount, out, ast::CommentExp(Location(), new std::wstring(L"")));
+    }
+    catch (const ast::InternalAbort& ia)
+    {
         pDbl->DecreaseRef();
-        delete pDbl;
-        pDbl = NULL;
-
-        if (bOk == false)
-        {
-            return 0;
-        }
-
-        if (out.size() != 1)
-        {
-            return 0;
-        }
-
-        if (out[0]->isDouble())
-        {
-            types::Double* pDblOut = out[0]->getAs<types::Double>();
-            iRet = pDblOut->get(0) == 0 ? 0 : 1;
-            delete pDblOut;
-            pDblOut = NULL;
-
-            return iRet;
-        }
-        else if (out[0]->isBool())
-        {
-            types::Bool* pBoolOut = out[0]->getAs<types::Bool>();
-            iRet = pBoolOut->get(0) == 0 ? 0 : 1;
-            delete pBoolOut;
-            pBoolOut = NULL;
-
-            return iRet;
-        }
+        pDbl->killMe();
+        throw ia;
     }
-    return 0;
+    catch (const ast::InternalError& ie)
+    {
+        pDbl->DecreaseRef();
+        pDbl->killMe();
+        throw ie;
+    }
+
+    pDbl->DecreaseRef();
+    pDbl->killMe();
+
+    if (out.size() != 1)
+    {
+        char* pstrName = wide_string_to_UTF8(pCall->getName().c_str());
+        sprintf(errorMsg, _("%s: Wrong number of output argument(s): %d expected.\n"), pstrName, iRetCount);
+        FREE(pstrName);
+        throw ast::InternalError(errorMsg);
+    }
+
+    if (out[0]->isDouble())
+    {
+        types::Double* pDblOut = out[0]->getAs<types::Double>();
+        iRet = pDblOut->get(0) == 0 ? 0 : 1;
+        pDblOut->killMe();
+    }
+    else if (out[0]->isBool())
+    {
+        types::Bool* pBoolOut = out[0]->getAs<types::Bool>();
+        iRet = pBoolOut->get(0) == 0 ? 0 : 1;
+        pBoolOut->killMe();
+    }
+
+    return iRet;
 }
 
 int schur_sb02ox(double* _real, double* _img, double* _beta) // discrete
 {
     return dpythags(*_real, *_img) < fabs(*_beta) ? 1 : 0;
 }
-int schur_sb02ow(double* _real, double* _img, double* _beta) // continu
+int schur_sb02ow(double* _real, double* /*_img*/, double* _beta) // continu
 {
     return  (*_real < 0 && *_beta > 0) ||
             ((*_real > 0 && *_beta < 0) &&
@@ -101,61 +114,75 @@ int schur_sb02ow(double* _real, double* _img, double* _beta) // continu
 int schur_dgges(double* _real, double* _img, double* _beta)
 {
     types::Callable* pCall = ConfigVariable::getSchurFunction();
+    if (pCall == NULL)
+    {
+        return 0;
+    }
+
+    char errorMsg[256];
     int iRet = 0;
 
-    if (pCall)
+    types::typed_list in;
+    types::typed_list out;
+    types::optional_list opt;
+    int iRetCount = 1;
+
+    types::Double* pDblAlpha = new types::Double(*_real, *_img);
+    pDblAlpha->IncreaseRef();
+    types::Double* pDblBeta  = new types::Double(*_beta);
+    pDblBeta->IncreaseRef();
+    in.push_back(pDblAlpha);
+    in.push_back(pDblBeta);
+
+    try
+    {
+        // new std::wstring(L"") is delete in destructor of ast::CommentExp
+        pCall->invoke(in, opt, iRetCount, out, ast::CommentExp(Location(), new std::wstring(L"")));
+    }
+    catch (const ast::InternalAbort& ia)
+    {
+        pDblAlpha->DecreaseRef();
+        pDblAlpha->killMe();
+        pDblBeta->DecreaseRef();
+        pDblBeta->killMe();
+        throw ia;
+    }
+    catch (const ast::InternalError& ie)
     {
-        types::typed_list in;
-        types::typed_list out;
-        types::optional_list opt;
-        int iRetCount = 1;
-
-        types::Double* pDblAlpha = new types::Double(*_real, *_img);
-        pDblAlpha->IncreaseRef();
-        types::Double* pDblBeta  = new types::Double(*_beta);
-        pDblBeta->IncreaseRef();
-        in.push_back(pDblAlpha);
-        in.push_back(pDblBeta);
-
-        bool bOk = pCall->call(in, opt, iRetCount, out) == types::Function::OK;
         pDblAlpha->DecreaseRef();
-        delete pDblAlpha;
-        pDblAlpha = NULL;
+        pDblAlpha->killMe();
         pDblBeta->DecreaseRef();
-        delete pDblBeta;
-        pDblBeta = NULL;
-
-        if (bOk == false)
-        {
-            return 0;
-        }
-
-        if (out.size() != 1)
-        {
-            return 0;
-        }
-
-        if (out[0]->isDouble())
-        {
-            types::Double* pDblOut = out[0]->getAs<types::Double>();
-            iRet = pDblOut->get(0) == 0 ? 0 : 1;
-            delete pDblOut;
-            pDblOut = NULL;
-
-            return iRet;
-        }
-        else if (out[0]->isBool())
-        {
-            types::Bool* pBoolOut = out[0]->getAs<types::Bool>();
-            iRet = pBoolOut->get(0) == 0 ? 0 : 1;
-            delete pBoolOut;
-            pBoolOut = NULL;
-
-            return iRet;
-        }
+        pDblBeta->killMe();
+        throw ie;
     }
 
-    return 0;
+    pDblAlpha->DecreaseRef();
+    pDblAlpha->killMe();
+    pDblBeta->DecreaseRef();
+    pDblBeta->killMe();
+
+    if (out.size() != 1)
+    {
+        char* pstrName = wide_string_to_UTF8(pCall->getName().c_str());
+        sprintf(errorMsg, _("%s: Wrong number of output argument(s): %d expected.\n"), pstrName, iRetCount);
+        FREE(pstrName);
+        throw ast::InternalError(errorMsg);
+    }
+
+    if (out[0]->isDouble())
+    {
+        types::Double* pDblOut = out[0]->getAs<types::Double>();
+        iRet = pDblOut->get(0) == 0 ? 0 : 1;
+        pDblOut->killMe();
+    }
+    else if (out[0]->isBool())
+    {
+        types::Bool* pBoolOut = out[0]->getAs<types::Bool>();
+        iRet = pBoolOut->get(0) == 0 ? 0 : 1;
+        pBoolOut->killMe();
+    }
+
+    return iRet;
 }
 
 int schur_zb02mw(doublecomplex* _complex)
@@ -169,54 +196,66 @@ int schur_zb02mv(doublecomplex* _complex)
 int schur_zgees(doublecomplex* _complex)
 {
     types::Callable* pCall = ConfigVariable::getSchurFunction();
+    if (pCall == NULL)
+    {
+        return 0;
+    }
+
+    char errorMsg[256];
     int iRet = 0;
 
-    if (pCall)
-    {
-        types::typed_list in;
-        types::typed_list out;
-        types::optional_list opt;
-        int iRetCount = 1;
+    types::typed_list in;
+    types::typed_list out;
+    types::optional_list opt;
+    int iRetCount = 1;
 
-        types::Double* pDbl = new types::Double(_complex->r, _complex->i);
-        pDbl->IncreaseRef();
-        in.push_back(pDbl);
+    types::Double* pDbl = new types::Double(_complex->r, _complex->i);
+    pDbl->IncreaseRef();
+    in.push_back(pDbl);
 
-        bool bOk = pCall->call(in, opt, iRetCount, out) == types::Function::OK;
+    try
+    {
+        // new std::wstring(L"") is delete in destructor of ast::CommentExp
+        pCall->invoke(in, opt, iRetCount, out, ast::CommentExp(Location(), new std::wstring(L"")));
+    }
+    catch (const ast::InternalAbort& ia)
+    {
         pDbl->DecreaseRef();
-        delete pDbl;
-        pDbl = NULL;
-
-        if (bOk == false)
-        {
-            return 0;
-        }
-
-        if (out.size() != 1)
-        {
-            return 0;
-        }
-
-        if (out[0]->isDouble())
-        {
-            types::Double* pDblOut = out[0]->getAs<types::Double>();
-            iRet = pDblOut->get(0) == 0 ? 0 : 1;
-            delete pDblOut;
-            pDblOut = NULL;
-
-            return iRet;
-        }
-        else if (out[0]->isBool())
-        {
-            types::Bool* pBoolOut = out[0]->getAs<types::Bool>();
-            iRet = pBoolOut->get(0) == 0 ? 0 : 1;
-            delete pBoolOut;
-            pBoolOut = NULL;
-
-            return iRet;
-        }
+        pDbl->killMe();
+        throw ia;
+    }
+    catch (const ast::InternalError& ie)
+    {
+        pDbl->DecreaseRef();
+        pDbl->killMe();
+        throw ie;
+    }
+
+    pDbl->DecreaseRef();
+    pDbl->killMe();
+
+    if (out.size() != 1)
+    {
+        char* pstrName = wide_string_to_UTF8(pCall->getName().c_str());
+        sprintf(errorMsg, _("%s: Wrong number of output argument(s): %d expected.\n"), pstrName, iRetCount);
+        FREE(pstrName);
+        throw ast::InternalError(errorMsg);
+    }
+
+    if (out[0]->isDouble())
+    {
+        types::Double* pDblOut = out[0]->getAs<types::Double>();
+        iRet = pDblOut->get(0) == 0 ? 0 : 1;
+        pDblOut->killMe();
+    }
+    else if (out[0]->isBool())
+    {
+        types::Bool* pBoolOut = out[0]->getAs<types::Bool>();
+        iRet = pBoolOut->get(0) == 0 ? 0 : 1;
+        pBoolOut->killMe();
     }
-    return 0;
+
+    return iRet;
 }
 
 int schur_zb02ox(doublecomplex* _alpha, doublecomplex* _beta) // discrete
@@ -238,59 +277,74 @@ int schur_zb02ow(doublecomplex* _alpha, doublecomplex* _beta) // continu
 int schur_zgges(doublecomplex* _alpha, doublecomplex* _beta)
 {
     types::Callable* pCall = ConfigVariable::getSchurFunction();
+    if (pCall == NULL)
+    {
+        return 0;
+    }
+
+    char errorMsg[256];
     int iRet = 0;
 
-    if (pCall)
+    types::typed_list in;
+    types::typed_list out;
+    types::optional_list opt;
+    int iRetCount = 1;
+
+    types::Double* pDblAlpha = new types::Double(_alpha->r, _alpha->i);
+    pDblAlpha->IncreaseRef();
+    types::Double* pDblBeta  = new types::Double(_beta->r, _beta->i);
+    pDblBeta->IncreaseRef();
+    in.push_back(pDblAlpha);
+    in.push_back(pDblBeta);
+
+    try
+    {
+        // new std::wstring(L"") is delete in destructor of ast::CommentExp
+        pCall->invoke(in, opt, iRetCount, out, ast::CommentExp(Location(), new std::wstring(L"")));
+    }
+    catch (const ast::InternalAbort& ia)
+    {
+        pDblAlpha->DecreaseRef();
+        pDblAlpha->killMe();
+        pDblBeta->DecreaseRef();
+        pDblBeta->killMe();
+        throw ia;
+    }
+    catch (const ast::InternalError& ie)
     {
-        types::typed_list in;
-        types::typed_list out;
-        types::optional_list opt;
-        int iRetCount = 1;
-
-        types::Double* pDblAlpha = new types::Double(_alpha->r, _alpha->i);
-        pDblAlpha->IncreaseRef();
-        types::Double* pDblBeta  = new types::Double(_beta->r, _beta->i);
-        pDblBeta->IncreaseRef();
-        in.push_back(pDblAlpha);
-        in.push_back(pDblBeta);
-
-        bool bOk = pCall->call(in, opt, iRetCount, out) == types::Function::OK;
         pDblAlpha->DecreaseRef();
-        delete pDblAlpha;
-        pDblAlpha = NULL;
+        pDblAlpha->killMe();
         pDblBeta->DecreaseRef();
-        delete pDblBeta;
-        pDblBeta = NULL;
-
-        if (bOk == false)
-        {
-            return 0;
-        }
-
-        if (out.size() != 1)
-        {
-            return 0;
-        }
-
-        if (out[0]->isDouble())
-        {
-            types::Double* pDblOut = out[0]->getAs<types::Double>();
-            iRet = pDblOut->get(0) == 0 ? 0 : 1;
-            delete pDblOut;
-            pDblOut = NULL;
-
-            return iRet;
-        }
-        else if (out[0]->isBool())
-        {
-            types::Bool* pBoolOut = out[0]->getAs<types::Bool>();
-            iRet = pBoolOut->get(0) == 0 ? 0 : 1;
-            delete pBoolOut;
-            pBoolOut = NULL;
-
-            return iRet;
-        }
+        pDblBeta->killMe();
+        throw ie;
     }
-    return 0;
+
+    pDblAlpha->DecreaseRef();
+    pDblAlpha->killMe();
+    pDblBeta->DecreaseRef();
+    pDblBeta->killMe();
+
+    if (out.size() != 1)
+    {
+        char* pstrName = wide_string_to_UTF8(pCall->getName().c_str());
+        sprintf(errorMsg, _("%s: Wrong number of output argument(s): %d expected.\n"), pstrName, iRetCount);
+        FREE(pstrName);
+        throw ast::InternalError(errorMsg);
+    }
+
+    if (out[0]->isDouble())
+    {
+        types::Double* pDblOut = out[0]->getAs<types::Double>();
+        iRet = pDblOut->get(0) == 0 ? 0 : 1;
+        pDblOut->killMe();
+    }
+    else if (out[0]->isBool())
+    {
+        types::Bool* pBoolOut = out[0]->getAs<types::Bool>();
+        iRet = pBoolOut->get(0) == 0 ? 0 : 1;
+        pBoolOut->killMe();
+    }
+
+    return iRet;
 }
 
diff --git a/scilab/modules/linear_algebra/tests/nonreg_tests/bug_14030.dia.ref b/scilab/modules/linear_algebra/tests/nonreg_tests/bug_14030.dia.ref
new file mode 100644 (file)
index 0000000..f6f1475
--- /dev/null
@@ -0,0 +1,42 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2015 - Scilab Enterprises - Adeline CARNIS
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+// <-- CLI SHELL MODE -->
+// <-- Non-regression test for bug 14030 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/show_bug.cgi?id=14030
+//
+// <-- Short Description -->
+//    Linear Algebra demo crashed due to calling of schur and fft functions.
+// =============================================================================
+H=[1.    1.    1.    0.;
+2.   -1.    0.    1;
+1.    0.    1.    1.;
+0.    1.    2.   -1];
+ww=spec(H)
+ ww  = 
+    2.7320508
+  - 2.7320508
+    0.7320508
+  - 0.7320508
+function [flg]=sel(x,y)
+   flg=%f
+   if abs(x/y-ww(3))<0.0001|abs(x/y-ww(4))<0.00001 then flg=%t,end
+endfunction
+[X,d]=schur(H,eye(H),sel);
+assert_checkfalse(norm(X*X'-eye(X), 1)> 200*%eps);
+assert_checkequal(d, 2);
+// check error
+function [flg]=sel(x,y)
+endfunction
+Warning : redefining function: sel                     . Use funcprot(0) to avoid this message
+assert_checkfalse(execstr("[X,d]=schur(H,eye(H),sel)"   ,"errcatch") == 0);
+refMsg = msprintf(_("Undefined variable ''%s'' in function ''%s''."), "flg", "sel");
+assert_checkerror("[X,d]=schur(H,eye(H),sel)", refMsg);
+e = [0 1 0 0]';
+ksi = fft(e, -1);
+assert_checkequal(ksi, [1; -%i; -1; %i]);
diff --git a/scilab/modules/linear_algebra/tests/nonreg_tests/bug_14030.tst b/scilab/modules/linear_algebra/tests/nonreg_tests/bug_14030.tst
new file mode 100644 (file)
index 0000000..c8d5bc8
--- /dev/null
@@ -0,0 +1,44 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2015 - Scilab Enterprises - Adeline CARNIS
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+
+// <-- CLI SHELL MODE -->
+
+// <-- Non-regression test for bug 14030 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/show_bug.cgi?id=14030
+//
+// <-- Short Description -->
+//    Linear Algebra demo crashed due to calling of schur and fft functions.
+// =============================================================================
+
+H=[1.    1.    1.    0.;
+2.   -1.    0.    1;
+1.    0.    1.    1.;
+0.    1.    2.   -1];
+
+ww=spec(H)
+
+function [flg]=sel(x,y)
+   flg=%f
+   if abs(x/y-ww(3))<0.0001|abs(x/y-ww(4))<0.00001 then flg=%t,end
+endfunction
+
+[X,d]=schur(H,eye(H),sel);
+assert_checkfalse(norm(X*X'-eye(X), 1)> 200*%eps);
+assert_checkequal(d, 2);
+
+// check error
+function [flg]=sel(x,y)
+endfunction
+assert_checkfalse(execstr("[X,d]=schur(H,eye(H),sel)"   ,"errcatch") == 0);
+refMsg = msprintf(_("Undefined variable ''%s'' in function ''%s''."), "flg", "sel");
+assert_checkerror("[X,d]=schur(H,eye(H),sel)", refMsg);
+
+e = [0 1 0 0]';
+ksi = fft(e, -1);
+assert_checkequal(ksi, [1; -%i; -1; %i]);