changeset 32215:ce1ae40de0f0 stable

subsasgn: Avoid panic on invalid field names (bug #64213). * libinterp/octave-value/ov-struct.cc (octave_struct::subsasgn, octave_scalar_struct::subsasgn): Throw an exception if field name is not a string instead of panicking. Add tests.
author Markus Mützel <markus.muetzel@gmx.de>
date Fri, 28 Jul 2023 16:24:32 +0200
parents 3321783e9fe5
children f8b53be9844e ae8c5b698912
files libinterp/octave-value/ov-struct.cc
diffstat 1 files changed, 56 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/octave-value/ov-struct.cc	Mon Jul 24 13:30:54 2023 -0400
+++ b/libinterp/octave-value/ov-struct.cc	Fri Jul 28 16:24:32 2023 +0200
@@ -306,7 +306,7 @@
   octave_value t_rhs = rhs;
 
   if (idx.front ().empty ())
-    error ("missing index in indexed assignment");
+    error ("subsasgn: missing index in indexed assignment");
 
   if (n > 1 && ! (type.length () == 2 && type[0] == '(' && type[1] == '.'))
     {
@@ -321,9 +321,11 @@
 
                 octave_value_list key_idx = *++p;
 
-                panic_if (key_idx.length () != 1);
-
-                std::string key = key_idx(0).string_value ();
+                if (key_idx.length () != 1)
+                  error ("subsasgn: dynamic structure field names must be strings");
+
+                std::string key
+                  = key_idx(0).xstring_value ("dynamic structure field names must be strings");
 
                 maybe_warn_invalid_field_name (key, "subsasgn");
 
@@ -377,9 +379,11 @@
           {
             octave_value_list key_idx = idx.front ();
 
-            panic_if (key_idx.length () != 1);
-
-            std::string key = key_idx(0).string_value ();
+            if (key_idx.length () != 1)
+              error ("subsasgn: dynamic structure field names must be strings");
+
+            std::string key
+              = key_idx(0).xstring_value ("subsasgn: dynamic structure field names must be strings");
 
             maybe_warn_invalid_field_name (key, "subsasgn");
 
@@ -443,9 +447,11 @@
             octave_value_list key_idx = *++p;
             octave_value_list idxf = idx.front ();
 
-            panic_if (key_idx.length () != 1);
-
-            std::string key = key_idx(0).string_value ();
+            if (key_idx.length () != 1)
+              error ("subsasgn: dynamic structure field names must be strings");
+
+            std::string key
+              = key_idx(0).xstring_value ("subsasgn: dynamic structure field names must be strings");
 
             maybe_warn_invalid_field_name (key, "subsasgn");
 
@@ -514,9 +520,11 @@
       {
         octave_value_list key_idx = idx.front ();
 
-        panic_if (key_idx.length () != 1);
-
-        std::string key = key_idx(0).string_value ();
+        if (key_idx.length () != 1)
+          error ("subsasgn: dynamic structure field names must be strings");
+
+        std::string key
+          = key_idx(0).xstring_value ("subsasgn: dynamic structure field names must be strings");
 
         maybe_warn_invalid_field_name (key, "subsasgn");
 
@@ -558,6 +566,21 @@
   return retval;
 }
 
+/*
+%!test
+%! x(1:2) = struct ();
+%! idx = struct ("type", {"()", ".", "."}, "subs", {{1}, "a", "b"});
+%! x = subsasgn (x, idx, 42);
+%! assert (x(1).a.b, 42);
+%! assert (isempty (x(2).a));
+
+%!test <*64213>
+%! x(1:2) = struct ();
+%! idx = struct ("type", {"()", "."}, "subs", {{1}, {"a", "b"}});
+%! fail ("x = subsasgn (x, idx, 42);", ...
+%!       "structure field names must be strings");
+*/
+
 octave_value
 octave_struct::do_index_op (const octave_value_list& idx, bool resize_ok)
 {
@@ -1221,7 +1244,7 @@
   octave_value retval;
 
   if (idx.front ().empty ())
-    error ("missing index in indexed assignment");
+    error ("subsasgn: missing index in indexed assignment");
 
   if (type[0] == '.')
     {
@@ -1231,9 +1254,11 @@
 
       octave_value_list key_idx = idx.front ();
 
-      panic_if (key_idx.length () != 1);
-
-      std::string key = key_idx(0).string_value ();
+      if (key_idx.length () != 1)
+        error ("subsasgn: structure field names must be strings");
+
+      std::string key
+        = key_idx(0).xstring_value ("subsasgn: structure field names must be strings");
 
       maybe_warn_invalid_field_name (key, "subsasgn");
 
@@ -1284,6 +1309,20 @@
   return retval;
 }
 
+/*
+%!test
+%! x = struct ();
+%! idx = struct ("type", ".", "subs", {"a", "b"});
+%! x = subsasgn (x, idx, 42);
+%! assert (x.a.b, 42);
+
+%!test <*64213>
+%! x = struct ();
+%! idx = struct ("type", ".", "subs", {{"a", "b"}});
+%! fail ("x = subsasgn (x, idx, 42)", ...
+%!       "structure field names must be strings");
+*/
+
 octave_value
 octave_scalar_struct::do_index_op (const octave_value_list& idx, bool resize_ok)
 {