summaryrefslogtreecommitdiff
path: root/op.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2013-06-22 18:46:00 -0700
committerFather Chrysostomos <sprout@cpan.org>2013-07-25 23:48:00 -0700
commit5608dcc62313f26a4bf696abe8e5fe687335a7e1 (patch)
tree1bfc56fdb4eedf0783ebe0f59a699c4b8a6ba4eb /op.c
parent2ca971d50b815fd6da6adac5c6691ac438237e05 (diff)
downloadperl-5608dcc62313f26a4bf696abe8e5fe687335a7e1.tar.gz
[perl #3105] Make 1..3 modification safe
This construct is optimised at compile time to an anonymous array with an implicit @{} around it if both arguments are constant. Modifying elements of that array produces wrong results the next time the same code is executed. If we mark each element of the array as PADTMP, then it will be treated like an operator’s return value (which it is) and get copied as appropriate.
Diffstat (limited to 'op.c')
-rw-r--r--op.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/op.c b/op.c
index f7cfe39018..dc8cf222c2 100644
--- a/op.c
+++ b/op.c
@@ -3353,6 +3353,8 @@ S_gen_constant_list(pTHX_ OP *o)
dVAR;
OP *curop;
const I32 oldtmps_floor = PL_tmps_floor;
+ SV **svp;
+ AV *av;
list(o);
if (PL_parser && PL_parser->error_count)
@@ -3375,7 +3377,11 @@ S_gen_constant_list(pTHX_ OP *o)
o->op_flags |= OPf_PARENS; /* and flatten \(1..2,3) */
o->op_opt = 0; /* needs to be revisited in rpeep() */
curop = ((UNOP*)o)->op_first;
- ((UNOP*)o)->op_first = newSVOP(OP_CONST, 0, SvREFCNT_inc_NN(*PL_stack_sp--));
+ av = (AV *)SvREFCNT_inc_NN(*PL_stack_sp--);
+ ((UNOP*)o)->op_first = newSVOP(OP_CONST, 0, (SV *)av);
+ if (AvFILLp(av) != -1)
+ for (svp = AvARRAY(av) + AvFILLp(av); svp >= AvARRAY(av); --svp)
+ SvPADTMP_on(*svp);
#ifdef PERL_MAD
op_getmad(curop,o,'O');
#else