diff options
author | Father Chrysostomos <sprout@cpan.org> | 2013-09-17 08:26:12 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2013-09-17 08:32:09 -0700 |
commit | acb3405042618ee03217199647b0b92863b95088 (patch) | |
tree | ac1c5fbc0d5860875d88a5042628bd02a99684e4 /op.c | |
parent | ccfc25677a64918883e67e4f4942fa0fb5556bfc (diff) | |
download | perl-acb3405042618ee03217199647b0b92863b95088.tar.gz |
[perl #119501] \(1+2) always referencing the same sv
2484f8dbbb hid the fact that constant folding happens by making 1+2
fold to a PADTMP, an SV that is never used as an lvalue and gets cop-
ied if one tries to use it that way.
The PADTMP mechanism is what allows \"$x" to return a new value each
time, even though ops like "$x" actually reuse the same scalar repeat-
edly to return values.
Because \ copies PADTMPs, \(1+2) ends up folding 1+2 to 3 (marked
PADTMP), which is then copied by the \ at compile time. (Constant
folding works by evaluating certain ops at compile time and then
inlining their returned value.) The result is that we have a folded
\3 where 3 is *not* marked PADTMP (the reference is, instead); hence
\(1+2) gives the same scalar each time, producing a value that can be
modified, affecting future evaluations.
The solution is to skip folding \ if its argument is a PADTMP.
Diffstat (limited to 'op.c')
-rw-r--r-- | op.c | 5 |
1 files changed, 5 insertions, 0 deletions
@@ -3347,6 +3347,11 @@ S_fold_constants(pTHX_ OP *o) break; case OP_REPEAT: if (o->op_private & OPpREPEAT_DOLIST) goto nope; + break; + case OP_SREFGEN: + if (cUNOPx(cUNOPo->op_first)->op_first->op_type != OP_CONST + || SvPADTMP(cSVOPx_sv(cUNOPx(cUNOPo->op_first)->op_first))) + goto nope; } if (PL_parser && PL_parser->error_count) |