summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-10-27 18:18:35 -0700
committerFather Chrysostomos <sprout@cpan.org>2012-10-28 02:04:57 -0700
commit78a84e43f7c23daa5ea308f75bfa99ce0fd2a841 (patch)
tree001ef7250e198ac14bd53a0ac879b3b830a5db11
parent12c45b2548283866d4ee5be5cea6c1cd072c3be9 (diff)
downloadperl-78a84e43f7c23daa5ea308f75bfa99ce0fd2a841.tar.gz
Stop regexp assignment from clobbering magic
$ perl5.10.0 -le '$1 = ${qr||}; print "ok"' Modification of a read-only value attempted at -e line 1. $ perl5.12.0 -le '$1 = ${qr||}; print "ok"' ok Wonderful! It can also cause blessings to be lost, or so I thought: sub curse { for my $obj ( ${$_[0]} ) { my $save = $obj; $obj = ${qr||}; $obj = $save; } } $y = bless \$x; print $y, "\n"; # main=SCALAR(0x825b70) curse $y; print $y, "\n"; # Bus error The OBJECT flag gets left on, but SvSTASH is null. Commit b9ad13acb set SvSTASH to null after copying the regexp struct. Commit 703c388dc did the same with SvMAGIC. In both cases, this was to avoid bugs involving magic and blessings being copied by = which should not happen. But both changes caused other bugs. Three months later, 6e1287864cd changed the order of the struct, such that SvMAGIC and SvSTASH are no longer copied from the parent regexp, rendering the aforementioned changes no longer necessary.
-rw-r--r--regcomp.c2
-rw-r--r--t/op/qr.t12
2 files changed, 11 insertions, 3 deletions
diff --git a/regcomp.c b/regcomp.c
index 6a106f87a6..f676645050 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -14193,8 +14193,6 @@ Perl_reg_temp_copy (pTHX_ REGEXP *ret_x, REGEXP *rx)
memcpy(&(ret->xpv_cur), &(r->xpv_cur),
sizeof(regexp) - STRUCT_OFFSET(regexp, xpv_cur));
SvLEN_set(ret_x, 0);
- SvSTASH_set(ret_x, NULL);
- SvMAGIC_set(ret_x, NULL);
if (r->offs) {
const I32 npar = r->nparens+1;
Newx(ret->offs, npar, regexp_paren_pair);
diff --git a/t/op/qr.t b/t/op/qr.t
index 9d78abf216..fb82d73d6e 100644
--- a/t/op/qr.t
+++ b/t/op/qr.t
@@ -7,7 +7,7 @@ BEGIN {
require './test.pl';
}
-plan(tests => 21);
+plan(tests => 24);
sub r {
return qr/Good/;
@@ -72,3 +72,13 @@ is $_, "bazbar", '[perl #96230] s/$qr// does not reuse last pat';
my $x = 1.1; $x = ${qr//};
pass 'no assertion failure when upgrading NV to regexp';
}
+
+sub TIESCALAR{bless[]}
+sub STORE { is ref\pop, "REGEXP", "stored regexp" }
+tie my $t, "";
+$t = ${qr||};
+ok tied $t, 'tied var is still tied after regexp assignment';
+
+bless \my $t2;
+$t2 = ${qr||};
+is ref \$t2, 'main', 'regexp assignment is not maledictory';