This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Stop values from ‘sticking’ to @- and @+ elems
authorFather Chrysostomos <sprout@cpan.org>
Fri, 26 Jul 2013 01:08:23 +0000 (18:08 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sun, 25 Aug 2013 19:25:23 +0000 (12:25 -0700)
commit232af1f839acc29d9ac336d13ff67802d236c38b
tree88b77f03c37a8c3d9be88de6822e11031523aafe
parent75d43e96c14b942bfcfb92795255377905baf38d
Stop values from ‘sticking’ to @- and @+ elems

These arrays are very similar to tied arrays, in that the elements are
created on the fly when looked up.  So push @_, \$+[0], \$+[0], will
push references to two different scalars on to @_.

That they are created on the fly prevents this bug from showing up
in most code:  If you reference the element you can observe that, on
FETCH, it gets set to the corresponding offset *if* the last match has
a set of capturing parentheses with the right number.  Otherwise, the
value in the element is left as-is.

So, doing another pattern match with, say, 5 captures and then another
with fewer will leave $+[5] and $-[5] holding values from the first
match, if there is a FETCH in between the two matches:

$ perl -le '"  "=~/()()()()(..)/; $_ = \$+[5]; print $$_; ""=~ /()/; print $$_;'
2
2

And attempts at assignment will succeed, even though they croak:

$ perl -le 'for ($-[0]) { eval { $_ = *foo }; print $_ }'
*main::foo

The solution here is to make the magic ‘get’ handler set the SV
no matter what, instead of just setting it when it refers to a
valid offset.
mg.c
t/re/pat.t