Author: chromatic
Date: Sun Aug 17 14:49:39 2008
New Revision: 30286

Modified:
   trunk/src/pmc/namespace.pmc
   trunk/t/pmc/namespace.t

Log:
[PMC] Fixed co-recursion bug in NameSpace, when iterating through its contents.
The problem is that, when the key is a Key and not a String, sometimes there's
an infinite loop when the Key isn't a string, integer, or PMC key -- the
default path for the switch in key_string() calls the get_string() vtable entry
on the key, which calls key_string(), which....

The short-term solution is to call the parent PMC (Hash) implementation of
get_pmc_keyed() and return the results, if they're accurate.  This fixes the
crash and keeps Rakudo working.  Replacing the body of the vtable entry with
the SUPER() call breaks Rakudo.

The long-term solution is to fix the Key PMC, which is poorly designed and
poorly implemented.

See RT #57668 and RT #58040, for starters.

Modified: trunk/src/pmc/namespace.pmc
==============================================================================
--- trunk/src/pmc/namespace.pmc (original)
+++ trunk/src/pmc/namespace.pmc Sun Aug 17 14:49:39 2008
@@ -382,26 +382,26 @@
     }
 
     VTABLE PMC *get_pmc_keyed(PMC *key) {
-        PMC    *ns = SELF;
+        PMC    *ns = SUPER(key);
 
-        if (key->vtable->base_type == enum_class_String)
-            return SELF.get_pmc_keyed_str(VTABLE_get_string(INTERP, key));
+        if (!PMC_IS_NULL(ns))
+            return ns;
+
+        ns = SELF;
 
         if (key->vtable->base_type == enum_class_Key) {
-            while (key) {
-                STRING * const part = key_string(INTERP, key);
-                key  = key_next(INTERP, key);
+            STRING * const part = key_string(INTERP, key);
+            key  = key_next(INTERP, key);
 
-                if (!key)
-                    return VTABLE_get_pmc_keyed_str(INTERP, ns, part);
+            if (!key)
+                return VTABLE_get_pmc_keyed_str(INTERP, ns, part);
 
-                ns = Parrot_get_namespace_keyed_str(INTERP, ns, part);
+            ns = Parrot_get_namespace_keyed_str(INTERP, ns, part);
 
-                if (PMC_IS_NULL(ns))
-                    return PMCNULL;
-            }
+            if (PMC_IS_NULL(ns))
+                return PMCNULL;
 
-            return ns;
+            return VTABLE_get_pmc_keyed(INTERP, ns, key);
         }
 
         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_GLOBAL_NOT_FOUND,

Modified: trunk/t/pmc/namespace.t
==============================================================================
--- trunk/t/pmc/namespace.t     (original)
+++ trunk/t/pmc/namespace.t     Sun Aug 17 14:49:39 2008
@@ -1736,7 +1736,7 @@
 /Null PMC access in get_string()/
 OUT
 
-pir_output_is( <<'CODE', <<OUT, "RT #57668", todo => "iterate through a 
NameSpace PMC, RT #57668" );
+pir_output_is( <<'CODE', <<OUT, "iterate through a NameSpace PMC" );
 .namespace [ 'bar' ]
 
 .sub 'main' :main

Reply via email to