diff options
author | Dave Mitchell <davem@fdisolutions.com> | 2004-03-27 01:54:09 +0000 |
---|---|---|
committer | Dave Mitchell <davem@fdisolutions.com> | 2004-03-27 01:54:09 +0000 |
commit | 781e754729fc501417aaa89f25dc83f904a17c5c (patch) | |
tree | acd18394b24e1dee6d0d3d8d64564808b9a1195c /pp.c | |
parent | 314d47789e6f2fb6e6cb6d9aa287d0766ea79b45 (diff) | |
download | perl-781e754729fc501417aaa89f25dc83f904a17c5c.tar.gz |
[perl #24200] string corruption with lvalue sub
Depending on the context, the same substr OP may want to return
a PVLV or an LV on subsequent invcations. If TARG is the wrong
type, use a mortal instead.
p4raw-id: //depot/perl@22599
Diffstat (limited to 'pp.c')
-rw-r--r-- | pp.c | 15 |
1 files changed, 13 insertions, 2 deletions
@@ -3038,6 +3038,19 @@ PP(pp_substr) if (utf8_curlen) sv_pos_u2b(sv, &pos, &rem); tmps += pos; + /* we either return a PV or an LV. If the TARG hasn't been used + * before, or is of that type, reuse it; otherwise use a mortal + * instead. Note that LVs can have an extended lifetime, so also + * dont reuse if refcount > 1 (bug #20933) */ + if (SvTYPE(TARG) > SVt_NULL) { + if ( (SvTYPE(TARG) == SVt_PVLV) + ? (!lvalue || SvREFCNT(TARG) > 1) + : lvalue) + { + TARG = sv_newmortal(); + } + } + sv_setpvn(TARG, tmps, rem); #ifdef USE_LOCALE_COLLATE sv_unmagic(TARG, PERL_MAGIC_collxfrm); @@ -3074,8 +3087,6 @@ PP(pp_substr) sv_setpvn(sv,"",0); /* avoid lexical reincarnation */ } - if (SvREFCNT(TARG) > 1) /* don't share the TARG (#20933) */ - TARG = sv_newmortal(); if (SvTYPE(TARG) < SVt_PVLV) { sv_upgrade(TARG, SVt_PVLV); sv_magic(TARG, Nullsv, PERL_MAGIC_substr, Nullch, 0); |