summaryrefslogtreecommitdiff
path: root/pp_ctl.c
diff options
context:
space:
mode:
authorDave Mitchell <davem@fdisolutions.com>2004-10-23 21:50:19 +0000
committerDave Mitchell <davem@fdisolutions.com>2004-10-23 21:50:19 +0000
commitb1464ded1acfef257a05adfafdd413fb0659a7e5 (patch)
tree01d7f3cc46e4b201b8310299bb721bbb4121eb1c /pp_ctl.c
parentf9d05ba35dc7d01260b38a6dc93f199c3b1d2c39 (diff)
downloadperl-b1464ded1acfef257a05adfafdd413fb0659a7e5.tar.gz
[perl #32039] Chained goto &sub drops data too early.
Change 22373 to stop a memory leak in goto &foo intead caused the elements of @_ to be freed too early. This revised fix just transfers the reifiedness of the old @_ to the new @_ p4raw-id: //depot/perl@23418
Diffstat (limited to 'pp_ctl.c')
-rw-r--r--pp_ctl.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index 2c18cf5fa5..4b894fcfd2 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -2248,7 +2248,6 @@ PP(pp_goto)
char *label;
int do_dump = (PL_op->op_type == OP_DUMP);
static char must_have_label[] = "goto must have label";
- AV *oldav = Nullav;
label = 0;
if (PL_op->op_flags & OPf_STACKED) {
@@ -2263,6 +2262,7 @@ PP(pp_goto)
SV** mark;
I32 items = 0;
I32 oldsave;
+ bool reified = 0;
retry:
if (!CvROOT(cv) && !CvXSUB(cv)) {
@@ -2304,16 +2304,16 @@ PP(pp_goto)
Copy(AvARRAY(av), SP + 1, items, SV*);
SvREFCNT_dec(GvAV(PL_defgv));
GvAV(PL_defgv) = cx->blk_sub.savearray;
+ CLEAR_ARGARRAY(av);
/* abandon @_ if it got reified */
if (AvREAL(av)) {
- oldav = av; /* delay until return */
+ reified = 1;
+ SvREFCNT_dec(av);
av = newAV();
av_extend(av, items-1);
AvFLAGS(av) = AVf_REIFY;
PAD_SVl(0) = (SV*)(cx->blk_sub.argarray = av);
}
- else
- CLEAR_ARGARRAY(av);
}
else if (CvXSUB(cv)) { /* put GvAV(defgv) back onto stack */
AV* av;
@@ -2332,11 +2332,13 @@ PP(pp_goto)
/* Now do some callish stuff. */
SAVETMPS;
- /* For reified @_, delay freeing till return from new sub */
- if (oldav)
- SAVEFREESV((SV*)oldav);
SAVEFREESV(cv); /* later, undo the 'avoid premature free' hack */
if (CvXSUB(cv)) {
+ if (reified) {
+ I32 index;
+ for (index=0; index<items; index++)
+ sv_2mortal(SP[-index]);
+ }
#ifdef PERL_XSUB_OLDSTYLE
if (CvOLDSTYLE(cv)) {
I32 (*fp3)(int,int,int);
@@ -2415,6 +2417,11 @@ PP(pp_goto)
Copy(mark,AvARRAY(av),items,SV*);
AvFILLp(av) = items - 1;
assert(!AvREAL(av));
+ if (reified) {
+ /* transfer 'ownership' of refcnts to new @_ */
+ AvREAL_on(av);
+ AvREIFY_off(av);
+ }
while (items--) {
if (*mark)
SvTEMP_off(*mark);