* Bug #16391 fixed: csvRead() was crashing with empty lines 47/21447/3
Clement David [Thu, 26 Mar 2020 17:02:33 +0000 (18:02 +0100)]
Change-Id: Icc27fc91e7549e34d70ea82025eb613f998cdfc5

scilab/CHANGES.md
scilab/modules/spreadsheet/src/c/csvRead.c
scilab/modules/spreadsheet/tests/nonreg_tests/bug_16391.tst [new file with mode: 0644]

index f015e36..8cb2cd2 100644 (file)
@@ -283,6 +283,7 @@ Bug Fixes
 * [#16369](https://bugzilla.scilab.org/16369): Right divisions / involving one or two sparse numerical matrices were no longer supported.
 * [#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.
 * [#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.
@@ -545,4 +546,4 @@ Bug Fixes
 * [#16333](https://bugzilla.scilab.org/16333): `tree_show` crashed for an input Xcos block.
 * [#16373](https://bugzilla.scilab.org/16373): Scilab Crashed or showing wrong output when running on Arm processor
 * [#16459](https://bugzilla.scilab.org/16459): The display of one column hypermatrix was wrong.
-* [#16463](https://bugzilla.scilab.org/16463): `matrix(sparse([]),[0 0])` yielded `[]` instead of `sparse([])`.
\ No newline at end of file
+* [#16463](https://bugzilla.scilab.org/16463): `matrix(sparse([]),[0 0])` yielded `[]` instead of `sparse([])`.
index aec92ca..bbb65fd 100644 (file)
@@ -21,7 +21,6 @@
 #include "expandPathVariable.h"
 #include "freeArrayOfString.h"
 #include "localization.h"
-#include "stringToComplex.h"
 #include "mclose.h"
 #include "mgetl.h"
 #include "mopen.h"
@@ -30,6 +29,7 @@
 #include "sci_malloc.h"
 #include "sciprint.h"
 #include "splitLine.h"
+#include "stringToComplex.h"
 #include "strsubst.h"
 #include <stdio.h>
 #include <string.h>
@@ -184,7 +184,6 @@ int csvTextScanInPlace(wchar_t** text, int nbLines, const wchar_t* separator,
 {
     stringToComplexError ierr = STRINGTOCOMPLEX_ERROR;
 
-
     // per line
     for (int i = 0; i < nbLines; i++)
     {
@@ -225,15 +224,14 @@ int csvTextScanInPlace(wchar_t** text, int nbLines, const wchar_t* separator,
                     break;
                 }
                 // adapt zeroIndex to be within the range
-                zeroIndex = i - iRange[0] + 1
-                            + (iRange[2] - iRange[0] + 1) * (j - iRange[1] + 1);
+                zeroIndex = i - iRange[0] + 1 + (iRange[2] - iRange[0] + 1) * (j - iRange[1] + 1);
             }
 
             // decode in double or string
             if (pDblRealValues != NULL)
             {
                 doublecomplex v = stringToComplexWInPlace(start, end, decimal,
-                                  TRUE, &ierr);
+                                                          TRUE, &ierr);
                 if (ierr == STRINGTOCOMPLEX_NO_ERROR)
                 {
                     // the imag part of a complex number is allocated on demand
@@ -242,9 +240,7 @@ int csvTextScanInPlace(wchar_t** text, int nbLines, const wchar_t* separator,
                         size_t n;
                         if (haveRange)
                         {
-                            n = (iRange[2] - iRange[0] + 1)
-                                * (iRange[3] - iRange[1] + 1)
-                                * sizeof(double);
+                            n = (iRange[2] - iRange[0] + 1) * (iRange[3] - iRange[1] + 1) * sizeof(double);
                         }
                         else
                         {
@@ -493,39 +489,33 @@ static void removeEmptyLinesAtEnd(wchar_t** lines, int* nonEmptyLines)
 // =============================================================================
 static void moveEmptyLinesToEnd(wchar_t** lines, int* nonEmptyLines)
 {
-    const int len = *nonEmptyLines;
-    int nbLinesToRemove = 0;
-
     if (lines)
     {
-        for (int i = 0; i < len; i++)
+        // move the blank lines at the end
+        int last = *nonEmptyLines - 1;
+        for (int i = last; i >= 0; i--)
         {
             if (hasOnlyBlankCharacters(&lines[i]))
             {
-                nbLinesToRemove++;
-
-                // move the lines at the end
-                for (int j = i + 1; j < len; i++, j++)
-                {
-                    // hopefully, empty lines have been flagged by hasOnlyBlankCharacters
-                    if (*(lines[j]) != L'\0')
-                    {
-                        // swap
-                        wchar_t* str = lines[i];
-                        lines[i] = lines[j];
-                        lines[j] = str;
-                    }
-                }
-
+                // swap
+                wchar_t* str = lines[i];
+                memmove(&lines[i], &lines[i+1], (last - i + 1) * sizeof(wchar_t*));
+                lines[last] = str;
+                last--;
             }
         }
-    }
 
-    *nonEmptyLines = len - nbLinesToRemove;
+        *nonEmptyLines = last + 1;
+    }
 }
 // =============================================================================
 static int hasOnlyBlankCharacters(wchar_t** line)
 {
+    if (*line == EMPTY_STR)
+    {
+        return 1;
+    }
+
     const wchar_t* iter = *line;
     while (*iter == L'\t' || *iter == L'\r' || *iter == L'\n' || *iter == L' ')
     {
diff --git a/scilab/modules/spreadsheet/tests/nonreg_tests/bug_16391.tst b/scilab/modules/spreadsheet/tests/nonreg_tests/bug_16391.tst
new file mode 100644 (file)
index 0000000..7d29050
--- /dev/null
@@ -0,0 +1,35 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2020 - ESI Group - Clement DAVID
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+//
+// <-- Non-regression test for bug 16391 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/show_bug.cgi?id=16391
+//
+// <-- Short Description -->
+// csvRead() crash with CSV files containing multiple empty lines
+
+dataset = fullfile(TMPDIR,"bug_16391.csv");
+
+
+fd = mopen(dataset, "w+");
+mputl("# a comment", fd);
+mputl("", fd);
+mputl("0.0,0,1", fd);
+mputl("", fd);
+mputl("", fd);
+mputl("", fd);
+mputl("", fd);
+mputl("", fd);
+mclose(fd);
+
+d = csvRead(dataset, ",", [],"double", [], "/#(.*)/" );
+assert_checkequal(d, [0,0,1]);
+