‘Attempt to bless into a ref’ with stale method caches
authorFather Chrysostomos <sprout@cpan.org>
Thu, 31 Oct 2013 13:03:53 +0000 (06:03 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Thu, 31 Oct 2013 22:47:03 +0000 (15:47 -0700)
As of v5.16.0-81-g234df27, SvAMAGIC has only meant potentially over-
loaded.  When method changes occur, the flag is turned on.  When over-
loading tables are calculated (the first time overloading is used),
the flag is turned off if it turns out there is no overloading.

At the time I did that, I assumed that all uses of SvAMAGIC were to
avoid the inefficient code path for non-overloaded objects.  What I
did not notice at the time was that SvAMAGIC is used in pp_bless to
determine whether an object used as a class name should be exempt from
‘Attempt to bless into a reference’.

Hence, the bizarre result:

$ ./perl -Ilib -e 'sub foo{} bless [], bless []'
$ ./perl -Ilib -e 'bless [], bless []'
Attempt to bless into a reference at -e line 1.

This commit makes both die consistently, as they did in 5.16.

pp.c
t/lib/croak/pp

diff --git a/pp.c b/pp.c
index f899a3f..d090069 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -617,9 +617,18 @@ PP(pp_bless)
 
        if (!ssv) goto curstash;
        SvGETMAGIC(ssv);
-       if (!SvAMAGIC(ssv) && SvROK(ssv))
+       if (SvROK(ssv)) {
+         if (!SvAMAGIC(ssv)) {
+          frog:
            Perl_croak(aTHX_ "Attempt to bless into a reference");
-       ptr = SvPV_nomg_const(ssv,len);
+         }
+         /* SvAMAGIC is on here, but it only means potentially overloaded,
+            so after stringification: */
+         ptr = SvPV_nomg_const(ssv,len);
+         /* We need to check the flag again: */
+         if (!SvAMAGIC(ssv)) goto frog;
+       }
+       else ptr = SvPV_nomg_const(ssv,len);
        if (len == 0)
            Perl_ck_warner(aTHX_ packWARN(WARN_MISC),
                           "Explicit blessing to '' (assuming package main)");
index 91fa40f..9a2057b 100644 (file)
@@ -12,3 +12,8 @@ $/ = \1;
 bless [], $/
 EXPECT
 Attempt to bless into a reference at - line 2.
+########
+# NAME Attempt to bless into a reference after method changes
+sub foo{} bless [], bless []
+EXPECT
+Attempt to bless into a reference at - line 1.