changeset 17696:cd5a6008ae72

Fix recursion segfault when setting axis parent to be child hggroup (bug #37927). * libinterp/corefcn/graphics.cc(set_parent): Check that new parent's parent is not object which is being reparented to avoid recursion. When condition occurs use object's current parent as parent property for new parent. If this sounds convoluted, it's because it is.
author Rik <rik@octave.org>
date Fri, 11 Oct 2013 21:21:50 -0700
parents 482222fe5b35
children 7ed397c8ca68
files libinterp/corefcn/graphics.cc
diffstat 1 files changed, 19 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/graphics.cc
+++ b/libinterp/corefcn/graphics.cc
@@ -2735,32 +2735,40 @@
 void
 base_properties::set_parent (const octave_value& val)
 {
-  double tmp = val.double_value ();
+  double hnp = val.double_value ();
 
   graphics_handle new_parent = octave_NaN;
 
   if (! error_state)
     {
-      if (tmp == __myhandle__)
+      if (hnp == __myhandle__)
         error ("set: can not set object parent to be object itself");
       else
         {
-          new_parent = gh_manager::lookup (tmp);
+          new_parent = gh_manager::lookup (hnp);
 
           if (new_parent.ok ())
             {
-              graphics_object parent_obj;
-
-              parent_obj = gh_manager::get_object (get_parent ());
-
-              parent_obj.remove_child (__myhandle__);
-
+              // Remove child from current parent
+              graphics_object old_parent_obj;
+              old_parent_obj = gh_manager::get_object (get_parent ());
+              old_parent_obj.remove_child (__myhandle__);
+
+              // Check new parent's parent is not this child to avoid recursion
+              graphics_object new_parent_obj;
+              new_parent_obj = gh_manager::get_object (new_parent);
+              if (new_parent_obj.get_parent () == __myhandle__)
+                {
+                  // new parent's parent gets child's original parent
+                  new_parent_obj.get_properties ().set_parent (get_parent ().as_octave_value ());
+                }
+
+              // Set parent property to new_parent and do adoption
               parent = new_parent.as_octave_value ();
-
               ::adopt (parent.handle_value (), __myhandle__);
             }
           else
-            error ("set: invalid graphics handle (= %g) for parent", tmp);
+            error ("set: invalid graphics handle (= %g) for parent", hnp);
         }
     }
   else