summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Mitchell <davem@fdisolutions.com>2003-08-24 16:52:00 +0100
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>2003-08-26 19:13:39 +0000
commit5dd42e15760f2e77ab3979bfe1b6aafaa9ff1227 (patch)
tree0afca94ca8522b7c1ac1afeea67258cd0ce57290
parentd7f1a795527ad4875d71a2e977851f754d4b7b3f (diff)
downloadperl-5dd42e15760f2e77ab3979bfe1b6aafaa9ff1227.tar.gz
improved 19064 (local $_[0] problems)
Message-ID: <20030824145159.GA12210@fdgroup.com> p4raw-id: //depot/perl@20909
-rw-r--r--pp_ctl.c8
-rw-r--r--pp_hot.c20
-rw-r--r--scope.c13
-rwxr-xr-xt/op/args.t6
4 files changed, 31 insertions, 16 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index 3c08f22e68..1fd6e01d38 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1883,6 +1883,7 @@ PP(pp_return)
switch (CxTYPE(cx)) {
case CXt_SUB:
popsub2 = TRUE;
+ cxstack_ix++; /* preserve cx entry on stack for use by POPSUB */
break;
case CXt_EVAL:
if (!(PL_in_eval & EVAL_KEEPERR))
@@ -1942,15 +1943,16 @@ PP(pp_return)
}
PL_stack_sp = newsp;
+ LEAVE;
/* Stack values are safe: */
if (popsub2) {
+ cxstack_ix--;
POPSUB(cx,sv); /* release CV and @_ ... */
}
else
sv = Nullsv;
PL_curpm = newpm; /* ... and pop $1 et al */
- LEAVE;
LEAVESUB(sv);
if (clear_errsv)
sv_setpv(ERRSV,"");
@@ -1985,6 +1987,7 @@ PP(pp_last)
dounwind(cxix);
POPBLOCK(cx,newpm);
+ cxstack_ix++; /* temporarily protect top context */
mark = newsp;
switch (CxTYPE(cx)) {
case CXt_LOOP:
@@ -2026,6 +2029,8 @@ PP(pp_last)
SP = newsp;
PUTBACK;
+ LEAVE;
+ cxstack_ix--;
/* Stack values are safe: */
switch (pop2) {
case CXt_LOOP:
@@ -2038,7 +2043,6 @@ PP(pp_last)
}
PL_curpm = newpm; /* ... and pop $1 et al */
- LEAVE;
LEAVESUB(sv);
return nextop;
}
diff --git a/pp_hot.c b/pp_hot.c
index 8b31f0b1bb..765f091979 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -2291,6 +2291,7 @@ PP(pp_leavesub)
SV *sv;
POPBLOCK(cx,newpm);
+ cxstack_ix++; /* temporarily protect top context */
TAINT_NOT;
if (gimme == G_SCALAR) {
@@ -2328,10 +2329,11 @@ PP(pp_leavesub)
}
PUTBACK;
+ LEAVE;
+ cxstack_ix--;
POPSUB(cx,sv); /* Stack values are safe: release CV and @_ ... */
PL_curpm = newpm; /* ... and pop $1 et al */
- LEAVE;
LEAVESUB(sv);
return pop_return();
}
@@ -2349,6 +2351,7 @@ PP(pp_leavesublv)
SV *sv;
POPBLOCK(cx,newpm);
+ cxstack_ix++; /* temporarily protect top context */
TAINT_NOT;
@@ -2384,9 +2387,10 @@ PP(pp_leavesublv)
* the refcounts so the caller gets a live guy. Cannot set
* TEMP, so sv_2mortal is out of question. */
if (!CvLVALUE(cx->blk_sub.cv)) {
+ LEAVE;
+ cxstack_ix--;
POPSUB(cx,sv);
PL_curpm = newpm;
- LEAVE;
LEAVESUB(sv);
DIE(aTHX_ "Can't modify non-lvalue subroutine call");
}
@@ -2395,9 +2399,10 @@ PP(pp_leavesublv)
EXTEND_MORTAL(1);
if (MARK == SP) {
if (SvFLAGS(TOPs) & (SVs_TEMP | SVs_PADTMP | SVf_READONLY)) {
+ LEAVE;
+ cxstack_ix--;
POPSUB(cx,sv);
PL_curpm = newpm;
- LEAVE;
LEAVESUB(sv);
DIE(aTHX_ "Can't return %s from lvalue subroutine",
SvREADONLY(TOPs) ? (TOPs == &PL_sv_undef) ? "undef"
@@ -2410,9 +2415,10 @@ PP(pp_leavesublv)
}
}
else { /* Should not happen? */
+ LEAVE;
+ cxstack_ix--;
POPSUB(cx,sv);
PL_curpm = newpm;
- LEAVE;
LEAVESUB(sv);
DIE(aTHX_ "%s returned from lvalue subroutine in scalar context",
(MARK > SP ? "Empty array" : "Array"));
@@ -2426,9 +2432,10 @@ PP(pp_leavesublv)
&& SvFLAGS(*mark) & (SVs_TEMP | SVs_PADTMP | SVf_READONLY)) {
/* Might be flattened array after $#array = */
PUTBACK;
+ LEAVE;
+ cxstack_ix--;
POPSUB(cx,sv);
PL_curpm = newpm;
- LEAVE;
LEAVESUB(sv);
DIE(aTHX_ "Can't return a %s from lvalue subroutine",
SvREADONLY(TOPs) ? "readonly value" : "temporary");
@@ -2480,10 +2487,11 @@ PP(pp_leavesublv)
}
PUTBACK;
+ LEAVE;
+ cxstack_ix--;
POPSUB(cx,sv); /* Stack values are safe: release CV and @_ ... */
PL_curpm = newpm; /* ... and pop $1 et al */
- LEAVE;
LEAVESUB(sv);
return pop_return();
}
diff --git a/scope.c b/scope.c
index 75f59cf538..33d891e13a 100644
--- a/scope.c
+++ b/scope.c
@@ -624,6 +624,9 @@ Perl_save_aelem(pTHX_ AV *av, I32 idx, SV **sptr)
SSPUSHINT(idx);
SSPUSHPTR(SvREFCNT_inc(*sptr));
SSPUSHINT(SAVEt_AELEM);
+ /* if it gets reified later, the restore will have the wrong refcnt */
+ if (!AvREAL(av) && AvREIFY(av))
+ SvREFCNT_inc(*sptr);
save_scalar_at(sptr);
sv = *sptr;
/* If we're localizing a tied array element, this new sv
@@ -706,7 +709,7 @@ Perl_leave_scope(pTHX_ I32 base)
value = (SV*)SSPOPPTR;
gv = (GV*)SSPOPPTR;
ptr = &GvSV(gv);
- SvREFCNT_dec(gv);
+ av = (AV*)gv; /* what to refcnt_dec */
goto restore_sv;
case SAVEt_GENERIC_PVREF: /* generic pv */
str = (char*)SSPOPPTR;
@@ -739,6 +742,7 @@ Perl_leave_scope(pTHX_ I32 base)
case SAVEt_SVREF: /* scalar reference */
value = (SV*)SSPOPPTR;
ptr = SSPOPPTR;
+ av = Nullav; /* what to refcnt_dec */
restore_sv:
sv = *(SV**)ptr;
DEBUG_S(PerlIO_printf(Perl_debug_log,
@@ -774,6 +778,8 @@ Perl_leave_scope(pTHX_ I32 base)
SvSETMAGIC(value);
PL_localizing = 0;
SvREFCNT_dec(value);
+ if (av) /* actually an av, hv or gv */
+ SvREFCNT_dec(av);
break;
case SAVEt_AV: /* array reference */
av = (AV*)SSPOPPTR;
@@ -983,13 +989,14 @@ Perl_leave_scope(pTHX_ I32 base)
value = (SV*)SSPOPPTR;
i = SSPOPINT;
av = (AV*)SSPOPPTR;
+ if (!AvREAL(av) && AvREIFY(av)) /* undo reify guard */
+ SvREFCNT_dec(value);
ptr = av_fetch(av,i,1);
if (ptr) {
sv = *(SV**)ptr;
if (sv && sv != &PL_sv_undef) {
if (SvTIED_mg((SV*)av, PERL_MAGIC_tied))
(void)SvREFCNT_inc(sv);
- SvREFCNT_dec(av);
goto restore_sv;
}
}
@@ -1007,8 +1014,8 @@ Perl_leave_scope(pTHX_ I32 base)
ptr = &HeVAL((HE*)ptr);
if (SvTIED_mg((SV*)hv, PERL_MAGIC_tied))
(void)SvREFCNT_inc(*(SV**)ptr);
- SvREFCNT_dec(hv);
SvREFCNT_dec(sv);
+ av = (AV*)hv; /* what to refcnt_dec */
goto restore_sv;
}
}
diff --git a/t/op/args.t b/t/op/args.t
index bac8fd0301..90a7d25771 100755
--- a/t/op/args.t
+++ b/t/op/args.t
@@ -1,6 +1,6 @@
#!./perl
-print "1..9\n";
+print "1..11\n";
# test various operations on @_
@@ -74,9 +74,6 @@ for (1..5) { try() }
++$ord;
print "ok $ord\n";
-# These tests disabled because the change #19064 was retracted.
-# http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2003-08/msg01485.html
-if (0) {
# bug #21542 local $_[0] causes reify problems and coredumps
sub local1 { local $_[0] }
@@ -89,4 +86,3 @@ sub local2 { local $_[0]; last L }
L: { local2 }
$ord++;
print "ok $ord\n";
-}