improved 19064 (local $_[0] problems)
Dave Mitchell [Sun, 24 Aug 2003 15:52:00 +0000 (16:52 +0100)]
Message-ID: <20030824145159.GA12210@fdgroup.com>

p4raw-id: //depot/perl@20909

pp_ctl.c
pp_hot.c
scope.c
t/op/args.t

index 3c08f22..1fd6e01 100644 (file)
--- 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;
 }
index 8b31f0b..765f091 100644 (file)
--- 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 75f59cf..33d891e 100644 (file)
--- 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;
                }
            }
index bac8fd0..90a7d25 100755 (executable)
@@ -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";
-}