# New Ticket Created by  NotFound 
# Please include the string:  [perl #54230]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=54230 >


Hello.

Parrot lacks loop avoidance in class hierarchy. This examples segfaults:

.sub main
  $P1 = newclass 'Foo'
  addparent $P1, $P1
.end

.sub main
  $P1 = newclass 'Foo'
  $P2 = newclass 'Bar'
  addparent $P1, $P2
  addparent $P2, $P1
.end

The attached patch modifies add_parent in class, checking that the new
parent is not self, and that none of his parents is.

It checks the complete list of parents to work the same way even on
override of isa. The intention is to avoid the fault in MRO, not to
forbid experiments with inheritance.

No tests yet, this patch is for evaluation and discussion.

-- 
Salu2
Index: src/pmc/class.pmc
===================================================================
--- src/pmc/class.pmc	(revisión: 27516)
+++ src/pmc/class.pmc	(copia de trabajo)
@@ -729,7 +729,7 @@
         STRING * const parent_name  = VTABLE_get_string(interp, parent);
 
         /* get number of direct parents */
-        const int parent_count      = VTABLE_elements(interp, _class->parents);
+        int parent_count      = VTABLE_elements(interp, _class->parents);
 
         int index; /* loop iterator */
 
@@ -744,6 +744,9 @@
             real_exception(interp, NULL, E_TypeError, "Parent isn't a Class.");
             return;
         }
+        /* Check is not self */
+        if (parent == SELF)
+            real_exception(interp, NULL, E_TypeError, "Can't be own parent");
 
         /* iterate over all direct parents, check whether this class already has
          * the parent being added.
@@ -768,6 +771,19 @@
 
         }
 
+        /* Check that none of the parents is self */
+        parent_count = VTABLE_elements(interp,
+            PARROT_CLASS(parent)->all_parents);
+        for (index = 0; index < parent_count; index++) {
+            /* get the next parent */
+            PMC * const current_parent = VTABLE_get_pmc_keyed_int(interp,
+                PARROT_CLASS(parent)->all_parents, index);
+            if (current_parent == SELF)
+                real_exception(interp, NULL, E_TypeError,
+                    "Loop in class hierarchy: '%S' is an ancestor of '%S'.",
+                    VTABLE_get_string(interp, SELF),
+                    VTABLE_get_string(interp, parent));
+        }
 
         /* Add to the lists of our immediate parents and all parents. */
         VTABLE_push_pmc(interp, _class->parents, parent);

Reply via email to