changeset 29133:cdc2f3799c85

Correctly handle short strings when saving to .mat files (-v6 or -v7) (bug #59591). * ls-mat5.cc (save_mat5_element_length): Correctly handle short strings. * load-save.cc: Add more tests for saving and loading different types.
author Markus Mützel <markus.muetzel@gmx.de>
date Wed, 02 Dec 2020 20:05:12 +0100
parents a948253f9976
children 3b1d005aabbf
files libinterp/corefcn/load-save.cc libinterp/corefcn/ls-mat5.cc
diffstat 2 files changed, 73 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/load-save.cc	Wed Dec 02 09:02:37 2020 -0800
+++ b/libinterp/corefcn/load-save.cc	Wed Dec 02 20:05:12 2020 +0100
@@ -165,8 +165,6 @@
   {
     bool retval = false;
 
-    std::string ascii_fname = sys::get_ASCII_filename (fname);
-
     std::ifstream file = sys::ifstream (fname.c_str (),
                                         std::ios::in | std::ios::binary);
 
@@ -1819,14 +1817,39 @@
 /*
 ## Save and load strings with "-v6"
 %!test
-%! A = A2 = ["foo"; "bar"];
-%! B = B2 = "foobar";
-%! C = C2 = {"foo", "bar"};
-%! D = D2 = {"Saint Barthélemy", "Saint Kitts and Nevis"};
+%! A = A2 = "foobar";  # normal string
+%! B = B2 = "a";  # short string
+%! C = C2 = ["foo"; "bar"];  # character matrix
+%! D = D2 = "ab".';  # short character matrix
+%! E = E2 = {"foo", "bar"};  # cell string
+%! F = F2 = {"Saint Barthélemy", "Saint Kitts and Nevis"};  % non-ASCII
 %! mat_file = [tempname(), ".mat"];
 %! unwind_protect
-%!   save (mat_file, "A", "B", "C", "D", "-v6");
-%!   clear ("A", "B", "C", "D");
+%!   save (mat_file, "A", "B", "C", "D", "E", "F", "-v6");
+%!   clear ("A", "B", "C", "D", "E", "F");
+%!   load (mat_file);
+%! unwind_protect_cleanup
+%!   unlink (mat_file);
+%! end_unwind_protect
+%! assert (A, A2);
+%! assert (B, B2);
+%! assert (C, C2);
+%! assert (D, D2);
+%! assert (E, E2);
+%! assert (F, F2);
+
+## Save and load strings with "-v7"
+%!testif HAVE_ZLIB
+%! A = A2 = "foobar";  # normal string
+%! B = B2 = "a";  # short string
+%! C = C2 = ["foo"; "bar"];  # character matrix
+%! D = D2 = "ab".';  # short character matrix
+%! E = E2 = {"foo", "bar"};  # cell string
+%! F = F2 = {"Saint Barthélemy", "Saint Kitts and Nevis"};  # non-ASCII
+%! mat_file = [tempname(), ".mat"];
+%! unwind_protect
+%!   save (mat_file, "A", "B", "C", "D", "E", "F", "-v7");
+%!   clear ("A", "B", "C", "D", "E", "F");
 %!   load (mat_file);
 %! unwind_protect_cleanup
 %!   unlink (mat_file);
@@ -1835,25 +1858,50 @@
 %! assert (B, B2);
 %! assert (C, C2);
 %! assert (D, D2);
+%! assert (E, E2);
+%! assert (F, F2);
 
-## Save and load strings with "-v7"
-%!testif HAVE_ZLIB
-%! A = A2 = ["foo"; "bar"];
-%! B = B2 = "foobar";
-%! C = C2 = {"foo", "bar"};
-%! D = D2 = {"Saint Barthélemy", "Saint Kitts and Nevis"};
+## Save and load struct with "-v6"
+%!test
+%! struc.a = "foobar";  # normal string
+%! struc.b = "a";  # short string
+%! struc.c = ["foo"; "bar"];  # character matrix
+%! struc.d = "ab".';  # short character matrix
+%! struc.e = {"foo", "bar"};  # cell string
+%! struc.f = {"Saint Barthélemy", "Saint Kitts and Nevis"};  # non-ASCII
+%! struc.g = [1 2 3];  # double vector
+%! struc.e = 1:5;  # range
+%! struc2 = struc;
 %! mat_file = [tempname(), ".mat"];
 %! unwind_protect
-%!   save (mat_file, "A", "B", "C", "D", "-v7");
-%!   clear ("A", "B", "C", "D");
+%!   save (mat_file, "struc", "-v6");
+%!   clear ("struc");
 %!   load (mat_file);
 %! unwind_protect_cleanup
 %!   unlink (mat_file);
 %! end_unwind_protect
-%! assert (A, A2);
-%! assert (B, B2);
-%! assert (C, C2);
-%! assert (D, D2);
+%! assert (struc, struc2);
+
+## Save and load struct with "-v7"
+%!test
+%! struc.a = "foobar";  # normal string
+%! struc.b = "a";  # short string
+%! struc.c = ["foo"; "bar"];  # character matrix
+%! struc.d = "ab".';  # short character matrix
+%! struc.e = {"foo", "bar"};  # cell string
+%! struc.f = {"Saint Barthélemy", "Saint Kitts and Nevis"};  # non-ASCII
+%! struc.g = [1 2 3];  # double vector
+%! struc.e = 1:5;  # range
+%! struc2 = struc;
+%! mat_file = [tempname(), ".mat"];
+%! unwind_protect
+%!   save (mat_file, "struc", "-v7");
+%!   clear ("struc");
+%!   load (mat_file);
+%! unwind_protect_cleanup
+%!   unlink (mat_file);
+%! end_unwind_protect
+%! assert (struc, struc2);
 
 ## Test input validation
 %!testif HAVE_ZLIB <*59225>
--- a/libinterp/corefcn/ls-mat5.cc	Wed Dec 02 09:02:37 2020 -0800
+++ b/libinterp/corefcn/ls-mat5.cc	Wed Dec 02 20:05:12 2020 +0100
@@ -2138,17 +2138,19 @@
       ret += 8;
 
       octave_idx_type str_len;
+      size_t sz_of = 1;
       if (u16_str)
         {
+          free (u16_str);
           // Count number of elements in converted string
-          str_len = 2 * n16_str;
-          free (u16_str);
+          str_len = n16_str;
+          sz_of = 2;
         }
       else
         str_len = chm.numel ();
 
       if (str_len > 2)
-        ret += PAD (str_len);
+        ret += PAD (sz_of * str_len);
     }
   else if (tc.issparse ())
     {
@@ -2265,7 +2267,6 @@
 
       for (octave_idx_type j = 0; j < nel; j++)
         {
-
           for (auto i = m.begin (); i != m.end (); i++)
             {
               const Cell elts = m.contents (i);