summaryrefslogtreecommitdiff
path: root/op.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2013-09-17 08:26:12 -0700
committerFather Chrysostomos <sprout@cpan.org>2013-09-17 08:32:09 -0700
commitacb3405042618ee03217199647b0b92863b95088 (patch)
treeac1c5fbc0d5860875d88a5042628bd02a99684e4 /op.c
parentccfc25677a64918883e67e4f4942fa0fb5556bfc (diff)
downloadperl-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.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/op.c b/op.c
index 2008cf10fc..f2a575cee4 100644
--- a/op.c
+++ b/op.c
@@ -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)