bug 15223 fix: some crashs with call 85/19485/1
Antoine ELIAS [Mon, 16 Oct 2017 08:14:05 +0000 (10:14 +0200)]
Change-Id: I6aa89def0b03926a5b3c7735fc2ce17fe66d9a91

scilab/CHANGES.md
scilab/modules/dynamic_link/sci_gateway/cpp/sci_call.cpp
scilab/modules/dynamic_link/tests/nonreg_tests/bug_15223.tst [new file with mode: 0644]
scilab/modules/dynamic_link/tests/unit_tests/call.tst
scilab/modules/dynamic_link/tests/unit_tests/call_tests.c [new file with mode: 0644]

index 3ae9b35..900d30f 100644 (file)
@@ -446,6 +446,7 @@ the [development mailing list](dev@lists.scilab.org) for a particular toolbox.
 * [#15199](http://bugzilla.scilab.org/show_bug.cgi?id=15199): Scilab crash when using fsolve for functions containing other functions.
 * [#15205](http://bugzilla.scilab.org/show_bug.cgi?id=15205): `get_scicos_version` returned the previous version.
 * [#15207](http://bugzilla.scilab.org/show_bug.cgi?id=15207): `xcos(scs_m)` did not work for sub-systems.
+* [#15223](http://bugzilla.scilab.org/show_bug.cgi?id=15223): `call` crashed in some cases.
 * [#15228](http://bugzilla.scilab.org/show_bug.cgi?id=15228): `get` error message fixed
 * [#15239](http://bugzilla.scilab.org/show_bug.cgi?id=15239): The console's properties .tag and .userdata were not displayed nor documented.
 * [#15236](http://bugzilla.scilab.org/show_bug.cgi?id=15236): The `isglobal` help page was inaccurate. Examples were erroneous.
index 4d8ce90..73beb20 100644 (file)
@@ -79,9 +79,9 @@ int sci_call(scilabEnv env, int nin, scilabVar* in, int nopt, scilabOpt opt, int
     }
 
     int pos = 1;
-    bool hasOutputs = true;
+    bool hasOutputs = false;
     //inputs
-    while (1)
+    while (pos < nin)
     {
         //check "out" to break loop
         if (isOut(env, in[pos]))
@@ -237,6 +237,16 @@ int sci_call(scilabEnv env, int nin, scilabVar* in, int nopt, scilabOpt opt, int
                     return 1;
                 }
 
+                //need to clone double input data to avoid modification
+                if (params[order - 1].type == L'd')
+                {
+                    int size = params[order - 1].row * params[order - 1].col * sizeof(double);
+                    double* dbls = (double*)malloc(size);
+                    memcpy(dbls, params[order - 1].data, size);
+                    params[order - 1].data = dbls;
+                    params[order - 1].alloc = true;
+                }
+
                 pos += 1;
                 output_order[output_pos] = order - 1;
             }
@@ -282,6 +292,16 @@ int sci_call(scilabEnv env, int nin, scilabVar* in, int nopt, scilabOpt opt, int
                         Scierror(999, _("%s: incompatible sizes between input and output variables.\n"), fname);
                         return 1;
                     }
+
+                    //need to clone double input data to avoid modification
+                    if (p.type == L'd')
+                    {
+                        int size = p.row * p.col * sizeof(double);
+                        double* dbls = (double*)malloc(size);
+                        memcpy(dbls, p.data, size);
+                        p.data = dbls;
+                        p.alloc = true;
+                    }
                 }
                 else // Otherwise allocate one
                 {
@@ -333,7 +353,7 @@ int sci_call(scilabEnv env, int nin, scilabVar* in, int nopt, scilabOpt opt, int
                              params[20].data, params[21].data, params[22].data, params[23].data, params[24].data, params[25].data, params[26].data, params[27].data, params[28].data, params[29].data);
 
     //create output variables
-    for (int i = 0; i < nout; ++i)
+    for (int i = 0; i < nout && hasOutputs; ++i)
     {
         Parameter& p = params[output_order[i]];
 
@@ -384,6 +404,8 @@ int sci_call(scilabEnv env, int nin, scilabVar* in, int nopt, scilabOpt opt, int
             }
         }
     }
+
+    //allocated data will be clean by structure dtor
     return STATUS_OK;
 }
 
diff --git a/scilab/modules/dynamic_link/tests/nonreg_tests/bug_15223.tst b/scilab/modules/dynamic_link/tests/nonreg_tests/bug_15223.tst
new file mode 100644 (file)
index 0000000..f3d628a
--- /dev/null
@@ -0,0 +1,36 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2017 - ESI - Antoine ELIAS
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- NO CHECK REF -->
+// <-- CLI SHELL MODE -->
+//
+// <-- Non-regression test for bug 15223 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/show_bug.cgi?id=15223
+//
+// <-- Short Description -->
+// call crashs in some cases
+
+c = [ ...
+    "#include <stdio.h>";
+    "";
+    "void bug_15223(void)";
+    "{";
+    "    printf(""call without input/output\n"");";
+    "}"]
+
+f = fullfile(TMPDIR, "bug_15223.c");
+mputl(c, f);
+cd(TMPDIR);
+libname = ilib_for_link("bug_15223", "bug_15223.c", [], "c");
+exec loader.sce;
+call("bug_15223");
+
+ulink();
+
+//if test finish without crash it is OK
index be1c930..5a04cb6 100644 (file)
@@ -7,30 +7,57 @@
 // =============================================================================
 
 // <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
 
-ilib_verbose(0);
-
-//================================================
-// test call
-//================================================
-foo=['void foo(double *a,double *b,double *c)';
-     '{ *c = *a + *b; }'  ];
-
-// we use TMPDIR for compilation 
-       
-if ~c_link('foo') then
-  curPath = pwd(); 
-  chdir(TMPDIR); 
-  mputl(foo,'foo.c');
-  
-  ilib_for_link(['foo'],'foo.c',[],"c");
-
-  // load the shared library 
-  exec loader.sce ;
-  chdir(curPath) ;
-end    
-
-//5+7 by C function
-v = call('foo',5,1,'d',7,2,'d','out',[1,1],3,'d');
-if v <> 12 then pause,end
-//================================================
+copyfile(fullfile(SCI, "modules/dynamic_link/tests/unit_tests", "call_tests.c"), fullfile(TMPDIR, "call_tests.c"));
+old = pwd();
+cd(TMPDIR);
+
+intef = ["call_0_0" "call_i1_0" "call_d1_0" "call_0_i1" "call_0_d1" "call_i1_i1" "call_d1_d1" "call_i1_i1_bis" "call_d1_d1_bis" "call_i1_d1"];
+
+ilib_for_link(intef, "call_tests.c", [], "c");
+exec loader.sce;
+
+//no args
+call("call_0_0");
+
+//1 out int
+v = call("call_i1_0", "out", [1 1], 1, "i");
+assert_checkequal(v, 42);
+
+//1 out double
+v = call("call_d1_0", "out", [1 1], 1, "d");
+assert_checkequal(v, %pi);
+
+//1 in int
+call("call_0_i1", 42, 1, "i");
+
+//1 in double
+call("call_0_d1", %pi, 1, "d");
+
+//1 in int, 1 out int
+v = call("call_i1_i1", 21, 1, "i", "out", [1 1], 1, "i");
+assert_checkequal(v, 42);
+v = call("call_i1_i1", 21, 1, "i", "out", 1);
+assert_checkequal(v, 42);
+
+//1 in double, 1 out double
+v = call("call_d1_d1", %pi, 1, "d", "out", [1 1], 1, "d");
+assert_checkequal(v, 2*%pi);
+v = call("call_d1_d1", %pi, 1, "d", "out", 1);
+assert_checkequal(v, 2*%pi);
+
+//1 in int, 1 out int
+v = call("call_i1_i1_bis", 21, 1, "i", "out", [1 1], 2, "i");
+assert_checkequal(v, 42);
+
+//1 in double, 1 out double
+v = call("call_d1_d1_bis", %pi, 1, "d", "out", [1 1], 2, "d");
+assert_checkequal(v, 2*%pi);
+
+//1 in int, 1 out double
+v = call("call_i1_d1", 21, 1, "i", "out", [1 1], 2, "d");
+assert_checkequal(v, 21*%pi);
+
+ulink();
+cd(old);
diff --git a/scilab/modules/dynamic_link/tests/unit_tests/call_tests.c b/scilab/modules/dynamic_link/tests/unit_tests/call_tests.c
new file mode 100644 (file)
index 0000000..4933ba4
--- /dev/null
@@ -0,0 +1,65 @@
+#include <stdio.h>
+
+#define M_PI 3.14159265358979323846
+
+//call_lhs_rhs
+
+void call_0_0(void)
+{
+    printf("call_0_0\n");
+}
+
+void call_i1_0(int* o1)
+{
+    printf("call_i1_0\n");
+    *o1 = 42;
+}
+
+void call_d1_0(double* o1)
+{
+    printf("call_d1_0\n");
+    *o1 = M_PI;
+}
+
+void call_0_i1(int* i1)
+{
+    printf("call_0_i1: %d\n", *i1);
+}
+
+void call_0_d1(double* d1)
+{
+    printf("call_0_d1: %f\n", *d1);
+}
+
+void call_i1_i1(int* io1)
+{
+    printf("call_i1_i1: %d\n", *io1);
+    *io1 *= 2;
+}
+
+void call_d1_d1(double* io1)
+{
+    printf("call_i1_i1: %f\n", *io1);
+    *io1 *= 2;
+}
+
+void call_i1_i1_bis(int* i1, int* o2)
+{
+    printf("call_i1_i1: %d\n", *i1);
+    *o2 = *i1 * 2;
+}
+
+void call_d1_d1_bis(double* i1, double* o2)
+{
+    printf("call_i1_i1: %d\n", *i1);
+    *o2 = *i1 * 2;
+}
+
+void call_i1_d1(int* i1, double* o2)
+{
+    printf("call_i1_i1: %d\n", *i1);
+    *o2 = *i1 * M_PI;
+}
+
+
+