summaryrefslogtreecommitdiff
path: root/doop.c
diff options
context:
space:
mode:
authorEric Brine <ikegami@adaelis.com>2010-07-31 01:56:43 -0700
committerRafael Garcia-Suarez <rgs@consttype.org>2010-08-13 13:36:29 +0200
commit2154eca77956ce145743765bea9ce269e6227984 (patch)
tree2fafd0f9d101cd03da45fb5d2f288b00c4eb00b9 /doop.c
parent0607bed5b8805b56401c29fc8c6d0f3737d5353f (diff)
downloadperl-2154eca77956ce145743765bea9ce269e6227984.tar.gz
Fix untimely destruction introduced by lvalue ops [RT#67838] by returning a TEMP instead of using TARG. Made appropriate TODO tests live.
Diffstat (limited to 'doop.c')
-rw-r--r--doop.c38
1 files changed, 16 insertions, 22 deletions
diff --git a/doop.c b/doop.c
index c1a357cc3e..903144ca86 100644
--- a/doop.c
+++ b/doop.c
@@ -1456,32 +1456,26 @@ Perl_do_kv(pTHX)
RETURN;
if (gimme == G_SCALAR) {
- IV i;
- dTARGET;
-
if (PL_op->op_flags & OPf_MOD || LVRET) { /* lvalue */
- if (SvTYPE(TARG) < SVt_PVLV) {
- sv_upgrade(TARG, SVt_PVLV);
- sv_magic(TARG, NULL, PERL_MAGIC_nkeys, NULL, 0);
- }
- LvTYPE(TARG) = 'k';
- if (LvTARG(TARG) != (const SV *)keys) {
- SvREFCNT_dec(LvTARG(TARG));
- LvTARG(TARG) = SvREFCNT_inc_simple(keys);
- }
- PUSHs(TARG);
- RETURN;
- }
-
- if (! SvTIED_mg((const SV *)keys, PERL_MAGIC_tied) )
- {
- i = HvKEYS(keys);
+ SV * const ret = sv_2mortal(newSV_type(SVt_PVLV)); /* Not TARG RT#67838 */
+ sv_magic(ret, NULL, PERL_MAGIC_nkeys, NULL, 0);
+ LvTYPE(ret) = 'k';
+ LvTARG(ret) = SvREFCNT_inc_simple(keys);
+ PUSHs(ret);
}
else {
- i = 0;
- while (hv_iternext(keys)) i++;
+ IV i;
+ dTARGET;
+
+ if (! SvTIED_mg((const SV *)keys, PERL_MAGIC_tied) ) {
+ i = HvKEYS(keys);
+ }
+ else {
+ i = 0;
+ while (hv_iternext(keys)) i++;
+ }
+ PUSHi( i );
}
- PUSHi( i );
RETURN;
}