summaryrefslogtreecommitdiff
path: root/pp_hot.c
diff options
context:
space:
mode:
authorDave Mitchell <davem@fdisolutions.com>2004-06-08 22:20:40 +0000
committerDave Mitchell <davem@fdisolutions.com>2004-06-08 22:20:40 +0000
commitdc09a129f20ae03853f77ccff57c311a4bae0f77 (patch)
tree663489bac3cd83eb94bbc18948f71b8f67ca0bb2 /pp_hot.c
parent72e5dea67722deb16f01b7f031b918a1919efc18 (diff)
downloadperl-dc09a129f20ae03853f77ccff57c311a4bae0f77.tar.gz
[perl #30061] double DESTROY in for loop
pp_iter decremented the ref count of the previous iterant before unaliasing it. This could lead to DESTROY being called with the loop variable still aliased to the freed value. If the DESTROY also contained a for loop with the same iterator variable, the freed value would get resurrected then freed for a second time. p4raw-id: //depot/perl@22913
Diffstat (limited to 'pp_hot.c')
-rw-r--r--pp_hot.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/pp_hot.c b/pp_hot.c
index 3a89b6f1c3..b7aad81bd5 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -1824,7 +1824,7 @@ PP(pp_iter)
{
dSP;
register PERL_CONTEXT *cx;
- SV* sv;
+ SV *sv, *oldsv;
AV* av;
SV **itersvp;
@@ -1852,8 +1852,9 @@ PP(pp_iter)
/* we need a fresh SV every time so that loop body sees a
* completely new SV for closures/references to work as
* they used to */
- SvREFCNT_dec(*itersvp);
+ oldsv = *itersvp;
*itersvp = newSVsv(cur);
+ SvREFCNT_dec(oldsv);
}
if (strEQ(SvPVX(cur), max))
sv_setiv(cur, 0); /* terminate next time */
@@ -1877,8 +1878,9 @@ PP(pp_iter)
/* we need a fresh SV every time so that loop body sees a
* completely new SV for closures/references to work as they
* used to */
- SvREFCNT_dec(*itersvp);
+ oldsv = *itersvp;
*itersvp = newSViv(cx->blk_loop.iterix++);
+ SvREFCNT_dec(oldsv);
}
RETPUSHYES;
}
@@ -1887,8 +1889,6 @@ PP(pp_iter)
if (cx->blk_loop.iterix >= (av == PL_curstack ? cx->blk_oldsp : AvFILL(av)))
RETPUSHNO;
- SvREFCNT_dec(*itersvp);
-
if (SvMAGICAL(av) || AvREIFY(av)) {
SV **svp = av_fetch(av, ++cx->blk_loop.iterix, FALSE);
if (svp)
@@ -1928,7 +1928,10 @@ PP(pp_iter)
sv = (SV*)lv;
}
+ oldsv = *itersvp;
*itersvp = SvREFCNT_inc(sv);
+ SvREFCNT_dec(oldsv);
+
RETPUSHYES;
}