Change 33458 by [EMAIL PROTECTED] on 2008/03/10 12:56:41

        Subject: Re: [PATCH] mg_magical() sometimes turns SvRMAGICAL on when it 
shouldn't
        From: Vincent Pit <[EMAIL PROTECTED]>
        Date: Fri, 08 Feb 2008 23:22:19 +0100
        Message-ID: <[EMAIL PROTECTED]>

Affected files ...

... //depot/perl/MANIFEST#1684 edit
... //depot/perl/ext/XS/APItest/APItest.pm#22 edit
... //depot/perl/ext/XS/APItest/APItest.xs#44 edit
... //depot/perl/ext/XS/APItest/t/rmagical.t#1 add
... //depot/perl/mg.c#522 edit

Differences ...

==== //depot/perl/MANIFEST#1684 (text) ====
Index: perl/MANIFEST
--- perl/MANIFEST#1683~33416~   2008-03-03 07:48:45.000000000 -0800
+++ perl/MANIFEST       2008-03-10 05:56:41.000000000 -0700
@@ -1259,6 +1259,7 @@
 ext/XS/APItest/t/op.t          XS::APItest: tests for OP related APIs
 ext/XS/APItest/t/printf.t      XS::APItest extension
 ext/XS/APItest/t/push.t                XS::APItest extension
+ext/XS/APItest/t/rmagical.t    XS::APItest extension
 ext/XS/APItest/t/svsetsv.t     Test behaviour of sv_setsv with/without 
PERL_CORE
 ext/XS/APItest/t/xs_special_subs_require.t     for require too
 ext/XS/APItest/t/xs_special_subs.t     Test that XS BEGIN/CHECK/INIT/END work

==== //depot/perl/ext/XS/APItest/APItest.pm#22 (text) ====
Index: perl/ext/XS/APItest/APItest.pm
--- perl/ext/XS/APItest/APItest.pm#21~33023~    2008-01-21 03:48:22.000000000 
-0800
+++ perl/ext/XS/APItest/APItest.pm      2008-03-10 05:56:41.000000000 -0700
@@ -22,9 +22,10 @@
                  apitest_exception mycroak strtab
                  my_cxt_getint my_cxt_getsv my_cxt_setint my_cxt_setsv
                  sv_setsv_cow_hashkey_core sv_setsv_cow_hashkey_notcore
+                 rmagical_cast rmagical_flags
 );
 
-our $VERSION = '0.13';
+our $VERSION = '0.14';
 
 use vars '$WARNINGS_ON_BOOTSTRAP';
 use vars map "\$${_}_called_PP", qw(BEGIN UNITCHECK CHECK INIT END);

==== //depot/perl/ext/XS/APItest/APItest.xs#44 (text) ====
Index: perl/ext/XS/APItest/APItest.xs
--- perl/ext/XS/APItest/APItest.xs#43~32699~    2007-12-22 03:28:02.000000000 
-0800
+++ perl/ext/XS/APItest/APItest.xs      2008-03-10 05:56:41.000000000 -0700
@@ -233,6 +233,13 @@
     return 0;
 }
 
+STATIC I32
+rmagical_a_dummy(pTHX_ IV idx, SV *sv) {
+    return 0;
+}
+
+STATIC MGVTBL rmagical_b = { 0 };
+
 #include "const-c.inc"
 
 MODULE = XS::APItest:Hash              PACKAGE = XS::APItest::Hash
@@ -813,6 +820,38 @@
 sv_setsv_cow_hashkey_notcore()
 
 void
+rmagical_cast(sv, type)
+    SV *sv;
+    SV *type;
+    PREINIT:
+       struct ufuncs uf;
+    PPCODE:
+       if (!SvOK(sv) || !SvROK(sv) || !SvOK(type)) { XSRETURN_UNDEF; }
+       sv = SvRV(sv);
+       if (SvTYPE(sv) != SVt_PVHV) { XSRETURN_UNDEF; }
+       uf.uf_val = rmagical_a_dummy;
+       uf.uf_set = NULL;
+       uf.uf_index = 0;
+       if (SvTRUE(type)) { /* b */
+           sv_magicext(sv, NULL, PERL_MAGIC_ext, &rmagical_b, NULL, 0);
+       } else { /* a */
+           sv_magic(sv, NULL, PERL_MAGIC_uvar, (char *) &uf, sizeof(uf));
+       }
+       XSRETURN_YES;
+
+void
+rmagical_flags(sv)
+    SV *sv;
+    PPCODE:
+       if (!SvOK(sv) || !SvROK(sv)) { XSRETURN_UNDEF; }
+       sv = SvRV(sv);
+        EXTEND(SP, 3); 
+       mXPUSHu(SvFLAGS(sv) & SVs_GMG);
+       mXPUSHu(SvFLAGS(sv) & SVs_SMG);
+       mXPUSHu(SvFLAGS(sv) & SVs_RMG);
+        XSRETURN(3);
+
+void
 BEGIN()
     CODE:
        sv_inc(get_sv("XS::APItest::BEGIN_called", GV_ADD|GV_ADDMULTI));

==== //depot/perl/ext/XS/APItest/t/rmagical.t#1 (text) ====
Index: perl/ext/XS/APItest/t/rmagical.t
--- /dev/null   2008-03-09 13:42:05.565441741 -0700
+++ perl/ext/XS/APItest/t/rmagical.t    2008-03-10 05:56:41.000000000 -0700
@@ -0,0 +1,29 @@
+#!perl
+
+# Consider two kinds of magic :
+# A : PERL_MAGIC_uvar, with get (but no set) magic
+# B : PERL_MAGIC_ext, with a zero vtbl
+# If those magic are attached on a sv in such a way that the MAGIC chain
+# looks like sv -> B -> A -> NULL (i.e. we first apply A and then B), then
+# mg_magical won't turn SvRMAGICAL on. However, if the chain is in the
+# opposite order (sv -> A -> B -> NULL), SvRMAGICAL used to be turned on.
+
+use strict;
+use warnings;
+
+use Test::More tests => 3;
+
+use_ok('XS::APItest');
+
+my (%h1, %h2);
+my @f;
+
+rmagical_cast(\%h1, 0); # A
+rmagical_cast(\%h1, 1); # B
[EMAIL PROTECTED] = rmagical_flags(\%h1);
+ok(!$f[2], "For sv -> B -> A -> NULL, SvRMAGICAL(sv) is false");
+
+rmagical_cast(\%h2, 1); # B
+rmagical_cast(\%h2, 0); # A
[EMAIL PROTECTED] = rmagical_flags(\%h2);
+ok(!$f[2], "For sv -> A -> B -> NULL, SvRMAGICAL(sv) is false");

==== //depot/perl/mg.c#522 (text) ====
Index: perl/mg.c
--- perl/mg.c#521~33291~        2008-02-12 05:15:20.000000000 -0800
+++ perl/mg.c   2008-03-10 05:56:41.000000000 -0700
@@ -123,16 +123,21 @@
     const MAGIC* mg;
     PERL_ARGS_ASSERT_MG_MAGICAL;
     PERL_UNUSED_CONTEXT;
-    for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
-       const MGVTBL* const vtbl = mg->mg_virtual;
-       if (vtbl) {
-           if (vtbl->svt_get && !(mg->mg_flags & MGf_GSKIP))
-               SvGMAGICAL_on(sv);
-           if (vtbl->svt_set)
-               SvSMAGICAL_on(sv);
-           if (!(SvFLAGS(sv) & (SVs_GMG|SVs_SMG)) || vtbl->svt_clear)
-               SvRMAGICAL_on(sv);
-       }
+    if ((mg = SvMAGIC(sv))) {
+       SvRMAGICAL_off(sv);
+       do {
+           const MGVTBL* const vtbl = mg->mg_virtual;
+           if (vtbl) {
+               if (vtbl->svt_get && !(mg->mg_flags & MGf_GSKIP))
+                   SvGMAGICAL_on(sv);
+               if (vtbl->svt_set)
+                   SvSMAGICAL_on(sv);
+               if (vtbl->svt_clear)
+                   SvRMAGICAL_on(sv);
+           }
+       } while ((mg = mg->mg_moremagic));
+       if (!(SvFLAGS(sv) & (SVs_GMG|SVs_SMG)))
+           SvRMAGICAL_on(sv);
     }
 }
 
End of Patch.

Reply via email to