summaryrefslogtreecommitdiffstats
path: root/scilab
diff options
context:
space:
mode:
authorAdeline CARNIS <adeline.carnis@scilab-enterprises.com>2020-07-31 15:21:58 +0200
committerClément DAVID <clement.david@esi-group.com>2020-10-19 15:30:08 +0200
commitd0c8c1144062176686c40c61f604e14cbca0e757 (patch)
treea8a77202f487eb8ef8ffa5bf4aa16c8a7a6d0fc4 /scilab
parent0f0fa3c20d2161ad432e7ca0264a63c78ca6d2f3 (diff)
downloadscilab-d0c8c1144062176686c40c61f604e14cbca0e757.zip
scilab-d0c8c1144062176686c40c61f604e14cbca0e757.tar.gz
* Bug 16508: csvTextScan did not handle well complex data.
An invalid read had also been fixed for some tests. All spreadsheet tests pass without any ASAN issue. https://bugzilla.scilab.org/show_bug.cgi?id=16508 Change-Id: I2db157ce71852d914f984460ec0049e697e132d1
Diffstat (limited to 'scilab')
-rw-r--r--scilab/CHANGES.md1
-rw-r--r--scilab/modules/spreadsheet/src/c/csvRead.c8
-rw-r--r--scilab/modules/spreadsheet/tests/nonreg_tests/bug_16508.dia.ref37
-rw-r--r--scilab/modules/spreadsheet/tests/nonreg_tests/bug_16508.tst39
-rw-r--r--scilab/modules/string/src/c/stringToComplex.c100
5 files changed, 132 insertions, 53 deletions
diff --git a/scilab/CHANGES.md b/scilab/CHANGES.md
index b1c467b..cf3ce0a 100644
--- a/scilab/CHANGES.md
+++ b/scilab/CHANGES.md
@@ -332,6 +332,7 @@ Bug Fixes
332* [#16474](https://bugzilla.scilab.org/16474): `imult(%z)` crashed Scilab. 332* [#16474](https://bugzilla.scilab.org/16474): `imult(%z)` crashed Scilab.
333* [#16488](https://bugzilla.scilab.org/16488): Concatenations mixing boolean and double with at least one operand being sparse were not supported. 333* [#16488](https://bugzilla.scilab.org/16488): Concatenations mixing boolean and double with at least one operand being sparse were not supported.
334* [#16496](https://bugzilla.scilab.org/16496): The `getdate` page should be rewritten: a) `getdate("s")` does NOT take leap seconds into account. b) `D=getdate(X)` is vectorized, accepts fractional seconds and returns them in `[0,1)` in D(10) instead of milliseconds. Moreover, the time referential of the result was unclear (time zone, daylight saving offset). 334* [#16496](https://bugzilla.scilab.org/16496): The `getdate` page should be rewritten: a) `getdate("s")` does NOT take leap seconds into account. b) `D=getdate(X)` is vectorized, accepts fractional seconds and returns them in `[0,1)` in D(10) instead of milliseconds. Moreover, the time referential of the result was unclear (time zone, daylight saving offset).
335* [#16508](https://bugzilla.scilab.org/16508): csvTextScan and csvRead did not handle well complex data.
335* [#16512](https://bugzilla.scilab.org/16512): 1 ./ uint8(0) crashes Scilab (idem with int8, uint16, int16, uint32, int32, uint64, int64). 336* [#16512](https://bugzilla.scilab.org/16512): 1 ./ uint8(0) crashes Scilab (idem with int8, uint16, int16, uint32, int32, uint64, int64).
336* [#16517](https://bugzilla.scilab.org/16517): `getdate("s")` truncated the actual time to integer seconds. `getdate(u)(10)` returned fractional seconds instead of milliseconds as `getdate()`. 337* [#16517](https://bugzilla.scilab.org/16517): `getdate("s")` truncated the actual time to integer seconds. `getdate(u)(10)` returned fractional seconds instead of milliseconds as `getdate()`.
337* [#16522](https://bugzilla.scilab.org/16522): `bitget(x,pos)` and `bitset(x,pos)` results could be wrong when `pos` is an encoded integer. 338* [#16522](https://bugzilla.scilab.org/16522): `bitget(x,pos)` and `bitset(x,pos)` results could be wrong when `pos` is an encoded integer.
diff --git a/scilab/modules/spreadsheet/src/c/csvRead.c b/scilab/modules/spreadsheet/src/c/csvRead.c
index 1fd1887..962b55a 100644
--- a/scilab/modules/spreadsheet/src/c/csvRead.c
+++ b/scilab/modules/spreadsheet/src/c/csvRead.c
@@ -231,7 +231,7 @@ int csvTextScanInPlace(wchar_t** text, int nbLines, const wchar_t* separator,
231 if (pDblRealValues != NULL) 231 if (pDblRealValues != NULL)
232 { 232 {
233 doublecomplex v = stringToComplexWInPlace(start, end, decimal, 233 doublecomplex v = stringToComplexWInPlace(start, end, decimal,
234 TRUE, &ierr); 234 TRUE, &ierr);
235 if (ierr == STRINGTOCOMPLEX_NO_ERROR) 235 if (ierr == STRINGTOCOMPLEX_NO_ERROR)
236 { 236 {
237 // the imag part of a complex number is allocated on demand 237 // the imag part of a complex number is allocated on demand
@@ -491,7 +491,7 @@ static void moveEmptyLinesToEnd(wchar_t** lines, int* nonEmptyLines)
491{ 491{
492 if (lines) 492 if (lines)
493 { 493 {
494 // move the blank lines at the end 494 // move the blank lines at the end and free them
495 int last = *nonEmptyLines - 1; 495 int last = *nonEmptyLines - 1;
496 for (int i = last; i >= 0; i--) 496 for (int i = last; i >= 0; i--)
497 { 497 {
@@ -499,7 +499,7 @@ static void moveEmptyLinesToEnd(wchar_t** lines, int* nonEmptyLines)
499 { 499 {
500 // swap 500 // swap
501 wchar_t* str = lines[i]; 501 wchar_t* str = lines[i];
502 memmove(&lines[i], &lines[i+1], (last - i + 1) * sizeof(wchar_t*)); 502 memmove(&lines[i], &lines[i + 1], (last - i) * sizeof(wchar_t*));
503 lines[last] = str; 503 lines[last] = str;
504 last--; 504 last--;
505 } 505 }
@@ -513,7 +513,7 @@ static int hasOnlyBlankCharacters(wchar_t** line)
513{ 513{
514 const wchar_t* iter = *line; 514 const wchar_t* iter = *line;
515 515
516 // EMPTY_STR is a tagged, non-allocated value for the empty string. It is 516 // EMPTY_STR is a tagged, non-allocated value for the empty string. It is
517 // used to flag a blank string. 517 // used to flag a blank string.
518 if (*line == EMPTY_STR) 518 if (*line == EMPTY_STR)
519 { 519 {
diff --git a/scilab/modules/spreadsheet/tests/nonreg_tests/bug_16508.dia.ref b/scilab/modules/spreadsheet/tests/nonreg_tests/bug_16508.dia.ref
new file mode 100644
index 0000000..373f2e3
--- /dev/null
+++ b/scilab/modules/spreadsheet/tests/nonreg_tests/bug_16508.dia.ref
@@ -0,0 +1,37 @@
1// =============================================================================
2// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3// Copyright (C) 2020 - ESI Group - Adeline CARNIS
4//
5// This file is distributed under the same license as the Scilab package.
6// =============================================================================
7//
8// <-- CLI SHELL MODE -->
9//
10// <-- Non-regression test for bug 16508 -->
11//
12// <-- Bugzilla URL -->
13// http://bugzilla.scilab.org/show_bug.cgi?id=16508
14//
15// <-- Short Description -->
16// csvTextScan and csvRead did not handle well complex data.
17text = ["Inf" "1-i" "i" "Nan-i"];
18expected = [%inf; 1-%i; %i; %nan-%i];
19M = csvTextScan(text);
20assert_checkequal(M, expected);
21File = TMPDIR + "/bug_16508.txt";
22mputl(text, File);
23M = csvRead(File);
24assert_checkequal(M, expected);
25text =["i" "1*i" "0*i" "2i"];
26expected = [%i; %i; 0; 2*%i];
27M = csvTextScan(text);
28assert_checkequal(M, expected);
29text =["%i" "1*%i" "0*%i" "2%i"];
30expected = [%i; %i; 0; 2*%i];
31M = csvTextScan(text);
32assert_checkequal(M, expected);
33text = ["Infi" "1+Nani"];
34csvTextScan(text)
35 ans =
36 0. + Infi
37 1. + Nani
diff --git a/scilab/modules/spreadsheet/tests/nonreg_tests/bug_16508.tst b/scilab/modules/spreadsheet/tests/nonreg_tests/bug_16508.tst
new file mode 100644
index 0000000..6bc4341
--- /dev/null
+++ b/scilab/modules/spreadsheet/tests/nonreg_tests/bug_16508.tst
@@ -0,0 +1,39 @@
1// =============================================================================
2// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3// Copyright (C) 2020 - ESI Group - Adeline CARNIS
4//
5// This file is distributed under the same license as the Scilab package.
6// =============================================================================
7//
8// <-- CLI SHELL MODE -->
9//
10// <-- Non-regression test for bug 16508 -->
11//
12// <-- Bugzilla URL -->
13// http://bugzilla.scilab.org/show_bug.cgi?id=16508
14//
15// <-- Short Description -->
16// csvTextScan and csvRead did not handle well complex data.
17
18text = ["Inf" "1-i" "i" "Nan-i"];
19expected = [%inf; 1-%i; %i; %nan-%i];
20M = csvTextScan(text);
21assert_checkequal(M, expected);
22
23File = TMPDIR + "/bug_16508.txt";
24mputl(text, File);
25M = csvRead(File);
26assert_checkequal(M, expected);
27
28text =["i" "1*i" "0*i" "2i"];
29expected = [%i; %i; 0; 2*%i];
30M = csvTextScan(text);
31assert_checkequal(M, expected);
32
33text =["%i" "1*%i" "0*%i" "2%i"];
34expected = [%i; %i; 0; 2*%i];
35M = csvTextScan(text);
36assert_checkequal(M, expected);
37
38text = ["Infi" "1+Nani"];
39csvTextScan(text) \ No newline at end of file
diff --git a/scilab/modules/string/src/c/stringToComplex.c b/scilab/modules/string/src/c/stringToComplex.c
index 63a7fd8..f211175 100644
--- a/scilab/modules/string/src/c/stringToComplex.c
+++ b/scilab/modules/string/src/c/stringToComplex.c
@@ -19,7 +19,7 @@
19#include "stringToDouble.h" 19#include "stringToDouble.h"
20#include "strsubst.h" 20#include "strsubst.h"
21#include "numericconstants_interface.h" 21#include "numericconstants_interface.h"
22 /* ========================================================================== */ 22/* ========================================================================== */
23#include <ctype.h> 23#include <ctype.h>
24#include <math.h> 24#include <math.h>
25#include <stdio.h> 25#include <stdio.h>
@@ -453,15 +453,6 @@ static int ParseNumberW(const wchar_t* tx)
453 int lookahead = 0; 453 int lookahead = 0;
454 int len = 0; 454 int len = 0;
455 455
456 if (tx[len] == L'0')
457 {
458 return lookahead;
459 }
460 if (tx[len] < 0)
461 {
462 return lookahead;
463 }
464
465 if ((tx[len] == L'+') || (tx[len] == L'-')) 456 if ((tx[len] == L'+') || (tx[len] == L'-'))
466 { 457 {
467 len++; 458 len++;
@@ -623,11 +614,11 @@ static stringToComplexError ParseComplexValue(const char* tx, BOOL bConvertByNAN
623 } 614 }
624 } 615 }
625 616
626 if (strcmp(inum_string, "+") == 0) 617 if (strcmp(inum_string, "+") == 0)
627 { 618 {
628 FREE(inum_string); 619 FREE(inum_string);
629 inum_string = os_strdup("+1"); 620 inum_string = os_strdup("+1");
630 } 621 }
631 622
632 if (strcmp(inum_string, "-") == 0) 623 if (strcmp(inum_string, "-") == 0)
633 { 624 {
@@ -699,8 +690,8 @@ static stringToComplexError ParseComplexValue(const char* tx, BOOL bConvertByNAN
699 ierr = STRINGTOCOMPLEX_ERROR; 690 ierr = STRINGTOCOMPLEX_ERROR;
700 } 691 }
701 } 692 }
702 } 693 }
703 694
704 695
705 FREE(rnum_string); 696 FREE(rnum_string);
706 FREE(inum_string); 697 FREE(inum_string);
@@ -948,33 +939,15 @@ static stringToComplexError ParseComplexValueWInPlace(wchar_t* tx, BOOL bConvert
948 *real = stringToDoubleWInPlace(tx, FALSE, &ierrDouble); 939 *real = stringToDoubleWInPlace(tx, FALSE, &ierrDouble);
949 *imag = 0; 940 *imag = 0;
950 941
951 /* test on strlen(tx) > 1 to remove case 'e' */ 942 if (ierrDouble == STRINGTODOUBLE_NO_ERROR)
952 if ((int)wcslen(tx) < 2)
953 { 943 {
954 if (ierrDouble == STRINGTODOUBLE_NO_ERROR) 944 ierr = (stringToComplexError)ierrDouble;
955 {
956 ierr = (stringToComplexError)ierrDouble;
957 }
958 else
959 {
960 if (bConvertByNAN)
961 {
962 ierrDouble = STRINGTODOUBLE_NOT_A_NUMBER;
963 *real = returnNAN();
964 *imag = 0;
965 }
966 else
967 {
968 *real = 0;
969 *imag = 0;
970 ierr = (stringToComplexError)ierrDouble;
971 }
972 }
973 } 945 }
974 else if (ierrDouble != STRINGTODOUBLE_NO_ERROR) 946 else if (ierrDouble != STRINGTODOUBLE_NO_ERROR)
975 { 947 {
976 // convert %i to i 948 // convert %i to i
977 for (wchar_t *it = tx, *jt = tx; *it != L'\0'; it++, jt++) 949 wchar_t* jt = tx;
950 for (wchar_t* it = tx; *it != L'\0'; it++, jt++)
978 { 951 {
979 if (it[0] == L'%' && it[1] == L'i') 952 if (it[0] == L'%' && it[1] == L'i')
980 { 953 {
@@ -982,6 +955,7 @@ static stringToComplexError ParseComplexValueWInPlace(wchar_t* tx, BOOL bConvert
982 } 955 }
983 *jt = *it; 956 *jt = *it;
984 } 957 }
958 *jt = '\0';
985 959
986 lnum = ParseNumberW(tx); 960 lnum = ParseNumberW(tx);
987 if (lnum <= 1) 961 if (lnum <= 1)
@@ -1018,19 +992,38 @@ static stringToComplexError ParseComplexValueWInPlace(wchar_t* tx, BOOL bConvert
1018 (inum_string[wcslen(inum_string) - 1] == L'j')) // The imaginary part looks like "a*%i" 992 (inum_string[wcslen(inum_string) - 1] == L'j')) // The imaginary part looks like "a*%i"
1019 { 993 {
1020 inum_string[wcslen(inum_string) - 1] = L'\0'; 994 inum_string[wcslen(inum_string) - 1] = L'\0';
1021 if (inum_string[wcslen(inum_string) - 1] == L'*') 995 gainImagI = 1.;
996 if (*inum_string == L'\0' && (wcslen(tx) == 0 || tx[wcslen(tx) - 1] == L'-'))
1022 { 997 {
1023 inum_string[wcslen(inum_string) - 1] = L'\0'; 998 inum_string = L"+1";
999 if (tx[wcslen(tx) - 1] == L'-')
1000 {
1001 gainImagI = -1.;
1002 }
1024 } 1003 }
1025 1004 else if (inum_string[wcslen(inum_string) - 1] == L'+')
1026 // *inum_string will be set to '\0' on leftstringInPlace, store the sign 1005 {
1027 // somewhere before! 1006 inum_string = L"+1";
1028 gainImagI = 1.; 1007 }
1029 if (*inum_string == L'-') 1008 else if (inum_string[wcslen(inum_string) - 1] == L'-')
1030 { 1009 {
1031 gainImagI = -1.; 1010 inum_string = L"-1";
1011 }
1012 else
1013 {
1014 if (inum_string[wcslen(inum_string) - 1] == L'*')
1015 {
1016 inum_string[wcslen(inum_string) - 1] = L'\0';
1017 }
1018
1019 // *inum_string will be set to '\0' on leftstringInPlace, store the sign
1020 // somewhere before!
1021 if (*inum_string == L'-')
1022 {
1023 gainImagI = -1.;
1024 }
1025 inum_string++;
1032 } 1026 }
1033 inum_string++;
1034 } 1027 }
1035 else if (inum_string[1] == L'i' || inum_string[1] == L'j') // The imaginary part looks like "%i*a". For instance if string() has been used 1028 else if (inum_string[1] == L'i' || inum_string[1] == L'j') // The imaginary part looks like "%i*a". For instance if string() has been used
1036 { 1029 {
@@ -1062,7 +1055,16 @@ static stringToComplexError ParseComplexValueWInPlace(wchar_t* tx, BOOL bConvert
1062 { 1055 {
1063 gainImagI = 0.; 1056 gainImagI = 0.;
1064 } 1057 }
1065 rnum_string = leftstringWInPlace(tx, lnum); 1058
1059 if (wcslen(tx) == 0 || (tx[0] == L'-' && wcslen(tx) == 1))
1060 {
1061 rnum_string = L"0";
1062 }
1063 else
1064 {
1065 rnum_string = leftstringWInPlace(tx, lnum);
1066 }
1067
1066 1068
1067 if (gainImagI != 0. && *rnum_string != L'\0' && *inum_string == L'\0') 1069 if (gainImagI != 0. && *rnum_string != L'\0' && *inum_string == L'\0')
1068 { 1070 {