Don't follow CvSTART() if CvROOT() is NULL.
Zefram [Fri, 10 May 2013 07:09:58 +0000 (09:09 +0200)]
For v5.17.2, blead switched to a slab allocator for OPs. During subroutine
compilation, the CV's slab is held in CvSTART(), to avoid extending every
PVCV by one more pointer. Once compilation is complete, the optree slab
pointer becomes accessible at an offset from CvROOT(), and CvSTART() is
set to point to the first OP. However, in some cases, PVCVs in the incomplete
state can become visible to Devel::Size, for example by following the
CvOUTSIDE() from BEGIN blocks. So we need to ignore CvSTART() if CvROOT() is
NULL. (Arguably we should always ignore CvSTART(), as the OP that it points to
should be accessible somewhere in the tree referenced by CvROOT(), but that
change can wait for a later date)

(see RT #83903 and perl's commit 8be227ab5eaa23f2)

CHANGES
Size.xs

diff --git a/CHANGES b/CHANGES
index c99fc5a..8c6c799 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,6 @@
 Revision history for Perl extension Devel::Size.
 
+ * Fix for v5.17.2's OP slab allocator [CPAN #83903]
  * Spelling fix to docs from gregor herrmann [CPAN #78766]
 
 0.78 2011-07-26 nicholas
diff --git a/Size.xs b/Size.xs
index 252dab2..3226910 100644 (file)
--- a/Size.xs
+++ b/Size.xs
@@ -802,7 +802,7 @@ sv_size(pTHX_ struct state *const st, const SV * const orig_thing,
     sv_size(aTHX_ st, (SV *)CvOUTSIDE(thing), recurse);
     if (CvISXSUB(thing)) {
        sv_size(aTHX_ st, cv_const_sv((CV *)thing), recurse);
-    } else {
+    } else if (CvROOT(thing)) {
        op_size(aTHX_ CvSTART(thing), st);
        op_size(aTHX_ CvROOT(thing), st);
     }