diff options
author | David Mitchell <davem@iabyn.com> | 2017-01-02 16:37:27 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2017-01-02 16:52:34 +0000 |
commit | 2108cbcf2fd75bfcc7b9c01563db7063a67549cf (patch) | |
tree | 0f3918332820d329b207c64b35a6f700c0fc775b /README | |
parent | 700779a8627cf5e47eedfe20b1c2eb3c865afb11 (diff) | |
download | perl-2108cbcf2fd75bfcc7b9c01563db7063a67549cf.tar.gz |
Handle chop(@a =~ tr///)
RT #130198
'chop(@x =~ tr/1/1/)' crashed with an assertion failure. Ditto for chomp.
There are two quirks which together cause this. First, the op tree for
a tr// is different from other bind ops:
$ perl -MO=Concise -e'$x =~ m/a/'
5 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 1 -e:1) v:{ ->3
4 </> match(/"a"/) vKS ->5
- <1> ex-rv2sv sK/1 ->4
3 <#> gvsv[*x] s ->4
$ perl -MO=Concise -e'$x =~ tr/a/b/'
5 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 1 -e:1) v:{ ->3
- <1> null vKS/2 ->5
- <1> ex-rv2sv sKRM/1 ->4
3 <#> gvsv[*x] s ->4
4 <"> trans sS ->5
Note that the argument for the match is a child of the match, while the
arg of the trans is an (earlier) sibing of the trans (linked by a common
null parent).
The normal code path that croaks when e.g. a match is seen in an lvalue
context,
$ perl -e'chop(@a =~ /a/)'
Can't modify pattern match (m//) in chop at -e line 1, near "/a/)
is skipped, since lvalue() is only called for the first child of a null op.
Fixing this is as simple as calling lvalue() on the RHS too if the RHS is
a trans op.
The second issue is that chop and chomp are special-cased not to flatten
an array; so
@b = 10..99;
chop $a, @b, $c;
pushes 3 items on the stack to pass to pp_chop, rather than 102. pp_chop()
itself then iterates over any array args.
The compiler was seeing the rv2av op in chop(@a =~ tr///) and was setting
the OPf_REF (don't flatten) flag on it. Which then caused pp_trans to
panic when its arg was an AV rather than a string.
This second issue is now moot, since after the fix suggested above, we
will have croaked before we reach the place where OPf_REF would be set.
This commit adds lots of tests, since tr/a/a/ and tr/a/b/r are
special-cased in terms of whether they are regarded as modifying the
var they are bound to.
Diffstat (limited to 'README')
0 files changed, 0 insertions, 0 deletions