]> git.vpit.fr Git - perl/modules/Variable-Magic.git/commitdiff
Store a placeholder in the wizards set for every manually generated signature.
authorVincent Pit <vince@profvince.com>
Sun, 1 Mar 2009 18:06:18 +0000 (19:06 +0100)
committerVincent Pit <vince@profvince.com>
Sun, 1 Mar 2009 18:06:18 +0000 (19:06 +0100)
Before that, it was possible to generate the same signature twice before actually defining the wizards.

As a result of this, casting from an obsolete signature now croaks.

Magic.xs
t/10-simple.t

index e9d9debe0c20c2d17b671d64682ef46be9d52aac..14a33f4a12a5cb7419ebc847b782dd402958f445 100644 (file)
--- a/Magic.xs
+++ b/Magic.xs
@@ -1088,7 +1088,6 @@ STATIC U16 vmg_sv2sig(pTHX_ SV *sv) {
 
 STATIC U16 vmg_wizard_sig(pTHX_ SV *wiz) {
 #define vmg_wizard_sig(W) vmg_wizard_sig(aTHX_ (W))
- char buf[8];
  U16 sig;
 
  if (SvROK(wiz)) {
@@ -1101,7 +1100,9 @@ STATIC U16 vmg_wizard_sig(pTHX_ SV *wiz) {
 
  {
   dMY_CXT;
-  if (!hv_exists(MY_CXT.wizards, buf, sprintf(buf, "%u", sig)))
+  char buf[8];
+  SV **old = hv_fetch(MY_CXT.wizards, buf, sprintf(buf, "%u", sig), 0);
+  if (!(old && SV2MGWIZ(*old)))
    croak(vmg_invalid_wiz);
  }
 
@@ -1110,8 +1111,6 @@ STATIC U16 vmg_wizard_sig(pTHX_ SV *wiz) {
 
 STATIC SV *vmg_wizard_wiz(pTHX_ SV *wiz) {
 #define vmg_wizard_wiz(W) vmg_wizard_wiz(aTHX_ (W))
- char buf[8];
- SV **old;
  U16 sig;
 
  if (SvROK(wiz)) {
@@ -1129,8 +1128,12 @@ STATIC SV *vmg_wizard_wiz(pTHX_ SV *wiz) {
 
  {
   dMY_CXT;
-  return (old = hv_fetch(MY_CXT.wizards, buf, sprintf(buf, "%u", sig), 0))
-          ? *old : NULL;
+  char buf[8];
+  SV **old = hv_fetch(MY_CXT.wizards, buf, sprintf(buf, "%u", sig), 0);
+  if (!(old && SV2MGWIZ(*old)))
+   croak(vmg_invalid_wiz);
+
+  return *old;
  }
 }
 
@@ -1255,13 +1258,16 @@ CODE:
    STRLEN len;
    char *sig = HePV(key, len);
    SV *sv;
-   const MGWIZ *w;
-   MAGIC *mg;
-   w  = SV2MGWIZ(HeVAL(key));
-   w  = vmg_wizard_clone(w);
-   sv = MGWIZ2SV(w);
-   mg = sv_magicext(sv, NULL, PERL_MAGIC_ext, &vmg_wizard_vtbl, NULL, 0);
-   mg->mg_private = SIG_WZO;
+   const MGWIZ *w = SV2MGWIZ(HeVAL(key));
+   if (w) {
+    MAGIC *mg;
+    w  = vmg_wizard_clone(w);
+    sv = MGWIZ2SV(w);
+    mg = sv_magicext(sv, NULL, PERL_MAGIC_ext, &vmg_wizard_vtbl, NULL, 0);
+    mg->mg_private = SIG_WZO;
+   } else {
+    sv = MGWIZ2SV(NULL);
+   }
    SvREADONLY_on(sv);
    if (!hv_store(hv, sig, len, sv, HeHASH(key))) croak("%s during CLONE", vmg_globstorefail);
   }
@@ -1315,7 +1321,8 @@ CODE:
  if (SvOK(svsig)) {
   SV **old;
   sig = vmg_sv2sig(svsig);
-  if ((old = hv_fetch(MY_CXT.wizards, buf, sprintf(buf, "%u", sig), 0))) {
+  old = hv_fetch(MY_CXT.wizards, buf, sprintf(buf, "%u", sig), 0);
+  if (old && SV2MGWIZ(*old)) {
    ST(0) = sv_2mortal(newRV_inc(*old));
    XSRETURN(1);
   }
@@ -1378,8 +1385,14 @@ OUTPUT:
 
 SV *gensig()
 PROTOTYPE:
+PREINIT:
+ U16 sig;
+ char buf[8];
 CODE:
- RETVAL = newSVuv(vmg_gensig());
+ dMY_CXT;
+ sig = vmg_gensig();
+ if (!hv_store(MY_CXT.wizards, buf, sprintf(buf, "%u", sig), MGWIZ2SV(NULL), 0)) croak(vmg_globstorefail);
+ RETVAL = newSVuv(sig);
 OUTPUT:
  RETVAL
 
@@ -1398,8 +1411,6 @@ PREINIT:
  SV *ret;
 CODE:
  wiz = vmg_wizard_wiz(wiz);
- if (!wiz)
-  XSRETURN_UNDEF;
  if (items > 2) {
   I32 i;
   args = newAV();
index 0b17fdeccd149fedaa977c0ee087b8965707a742..1617fdc997b152ee97779423b1acbbd4d06e2066 100644 (file)
@@ -3,10 +3,12 @@
 use strict;
 use warnings;
 
-use Test::More tests => 46;
+use Test::More tests => 48;
 
 use Variable::Magic qw/wizard gensig getsig cast dispell MGf_COPY MGf_DUP MGf_LOCAL VMG_UVAR/;
 
+my $inv_wiz_obj = qr/Invalid\s+wizard\s+object\s+at\s+\Q$0\E/;
+
 my $args = 8;
 ++$args if MGf_COPY;
 ++$args if MGf_DUP;
@@ -25,14 +27,18 @@ for (0 .. 3) {
 
 my $sig = gensig;
 
+my $a = 1;
+my $res = eval { cast $a, $sig };
+like($@, $inv_wiz_obj, 'cast from wrong sig croaks');
+is($res, undef,        'cast from wrong sig doesn\'t return anything');
+
 my $wiz = eval { wizard sig => $sig };
 is($@, '',             'wizard doesn\'t croak');
 ok(defined $wiz,       'wizard is defined');
 is(ref $wiz, 'SCALAR', 'wizard is a scalar ref');
 is($sig, getsig $wiz,  'wizard signature is correct');
 
-my $a = 1;
-my $res = eval { cast $a, $wiz };
+$res = eval { cast $a, $wiz };
 is($@, '', 'cast doesn\'t croak');
 ok($res,   'cast is valid');
 
@@ -45,12 +51,12 @@ is($@, '', 're-cast doesn\'t croak');
 ok($res,   're-cast is valid');
 
 $res = eval { dispell $a, gensig };
-like($@, qr/Invalid\s+wizard\s+object\s+at\s+\Q$0\E/, 're-dispell from wrong sig croaks');
-is($res, undef, 're-dispell from wrong sig doesn\'t return anything');
+like($@, $inv_wiz_obj, 're-dispell from wrong sig croaks');
+is($res, undef,        're-dispell from wrong sig doesn\'t return anything');
 
 $res = eval { dispell $a, undef };
-like($@, qr/Invalid\s+wizard\s+object\s+at\s+\Q$0\E/, 're-dispell from undef croaks');
-is($res, undef, 're-dispell from undef doesn\'t return anything');
+like($@, $inv_wiz_obj, 're-dispell from undef croaks');
+is($res, undef,        're-dispell from undef doesn\'t return anything');
 
 $res = eval { dispell $a, $sig };
 is($@, '', 're-dispell from good sig doesn\'t croak');
@@ -68,9 +74,9 @@ $sig = gensig;
 }
 my $c = 3;
 $res = eval { cast $c, $sig };
-is($@, '',      'cast from obsolete signature doesn\'t croak');
-is($res, undef, 'cast from obsolete signature returns undef');
+like($@, $inv_wiz_obj, 'cast from obsolete signature croaks');
+is($res, undef,        'cast from obsolete signature returns undef');
 
 $res = eval { cast $c, undef };
-like($@, qr/Invalid\s+wizard\s+object\s+at\s+\Q$0\E/, 'cast from undef croaks');
-is($res, undef, 'cast from undef doesn\'t return anything');
+like($@, $inv_wiz_obj, 'cast from undef croaks');
+is($res, undef,        'cast from undef doesn\'t return anything');