This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix -Wformat-security issues
[perl5.git] / pp_ctl.c
index 0fee02a..b0bc528 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -77,13 +77,13 @@ PP(pp_regcomp)
 {
     dVAR;
     dSP;
-    register PMOP *pm = (PMOP*)cLOGOP->op_other;
+    PMOP *pm = (PMOP*)cLOGOP->op_other;
     SV **args;
     int nargs;
     REGEXP *re = NULL;
     REGEXP *new_re;
     const regexp_engine *eng;
-    bool is_bare_re;
+    bool is_bare_re= FALSE;
 
     if (PL_op->op_flags & OPf_STACKED) {
        dMARK;
@@ -107,16 +107,29 @@ PP(pp_regcomp)
     assert (re != (REGEXP*) &PL_sv_undef);
     eng = re ? RX_ENGINE(re) : current_re_engine();
 
+    /*
+     In the below logic: these are basically the same - check if this regcomp is part of a split.
+
+    (PL_op->op_pmflags & PMf_split )
+    (PL_op->op_next->op_type == OP_PUSHRE)
+
+    We could add a new mask for this and copy the PMf_split, if we did
+    some bit definition fiddling first.
+
+    For now we leave this
+    */
+
     new_re = (eng->op_comp
                    ? eng->op_comp
                    : &Perl_re_op_compile
            )(aTHX_ args, nargs, pm->op_code_list, eng, re,
                &is_bare_re,
-               (pm->op_pmflags & RXf_PMf_COMPILETIME),
+                (pm->op_pmflags & RXf_PMf_FLAGCOPYMASK),
                pm->op_pmflags |
                    (PL_op->op_flags & OPf_SPECIAL ? PMf_USE_RE_EVAL : 0));
+
     if (pm->op_pmflags & PMf_HAS_CV)
-       ((struct regexp *)SvANY(new_re))->qr_anoncv
+       ReANY(new_re)->qr_anoncv
                        = (CV*) SvREFCNT_inc(PAD_SV(PL_op->op_targ));
 
     if (is_bare_re) {
@@ -129,7 +142,7 @@ PP(pp_regcomp)
           some day. */
        if (pm->op_type == OP_MATCH) {
            SV *lhs;
-           const bool was_tainted = PL_tainted;
+           const bool was_tainted = TAINT_get;
            if (pm->op_flags & OPf_STACKED)
                lhs = args[-1];
            else if (pm->op_private & OPpTARGET_MY)
@@ -138,22 +151,27 @@ PP(pp_regcomp)
            SvGETMAGIC(lhs);
            /* Restore the previous value of PL_tainted (which may have been
               modified by get-magic), to avoid incorrectly setting the
-              RXf_TAINTED flag further down. */
-           PL_tainted = was_tainted;
+              RXf_TAINTED flag with RX_TAINT_on further down. */
+           TAINT_set(was_tainted);
+#if NO_TAINT_SUPPORT
+            PERL_UNUSED_VAR(was_tainted);
+#endif
        }
        tmp = reg_temp_copy(NULL, new_re);
        ReREFCNT_dec(new_re);
        new_re = tmp;
     }
+
     if (re != new_re) {
        ReREFCNT_dec(re);
        PM_SETRE(pm, new_re);
     }
 
+
 #ifndef INCOMPLETE_TAINTS
-    if (PL_tainting && PL_tainted) {
+    if (TAINTING_get && TAINT_get) {
        SvTAINTED_on((SV*)new_re);
-       RX_EXTFLAGS(new_re) |= RXf_TAINTED;
+        RX_TAINT_on(new_re);
     }
 #endif
 
@@ -177,13 +195,13 @@ PP(pp_substcont)
 {
     dVAR;
     dSP;
-    register PERL_CONTEXT *cx = &cxstack[cxstack_ix];
-    register PMOP * const pm = (PMOP*) cLOGOP->op_other;
-    register SV * const dstr = cx->sb_dstr;
-    register char *s = cx->sb_s;
-    register char *m = cx->sb_m;
+    PERL_CONTEXT *cx = &cxstack[cxstack_ix];
+    PMOP * const pm = (PMOP*) cLOGOP->op_other;
+    SV * const dstr = cx->sb_dstr;
+    char *s = cx->sb_s;
+    char *m = cx->sb_m;
     char *orig = cx->sb_orig;
-    register REGEXP * const rx = cx->sb_rx;
+    REGEXP * const rx = cx->sb_rx;
     SV *nsv = NULL;
     REGEXP *old = PM_GETRE(pm);
 
@@ -216,18 +234,16 @@ PP(pp_substcont)
        if (CxONCE(cx) || s < orig ||
                !CALLREGEXEC(rx, s, cx->sb_strend, orig,
                             (s == m) + RX_GOFS(rx), cx->sb_targ, NULL,
-                            ((cx->sb_rflags & REXEC_COPY_STR)
-                             ? (REXEC_IGNOREPOS|REXEC_NOT_FIRST)
-                             : (REXEC_COPY_STR|REXEC_IGNOREPOS|REXEC_NOT_FIRST))))
+                                (REXEC_IGNOREPOS|REXEC_NOT_FIRST)))
        {
            SV *targ = cx->sb_targ;
 
            assert(cx->sb_strend >= s);
            if(cx->sb_strend > s) {
                 if (DO_UTF8(dstr) && !SvUTF8(targ))
-                     sv_catpvn_utf8_upgrade(dstr, s, cx->sb_strend - s, nsv);
+                     sv_catpvn_nomg_utf8_upgrade(dstr, s, cx->sb_strend - s, nsv);
                 else
-                     sv_catpvn(dstr, s, cx->sb_strend - s);
+                     sv_catpvn_nomg(dstr, s, cx->sb_strend - s);
            }
            if (RX_MATCH_TAINTED(rx)) /* run time pattern taint, eg locale */
                cx->sb_rxtainted |= SUBST_TAINT_PAT;
@@ -252,6 +268,7 @@ PP(pp_substcont)
                    SvUTF8_on(targ);
                SvPV_set(dstr, NULL);
 
+               PL_tainted = 0;
                mPUSHi(saviters - 1);
 
                (void)SvPOK_only_UTF8(targ);
@@ -260,7 +277,7 @@ PP(pp_substcont)
            /* update the taint state of various various variables in
             * preparation for final exit.
             * See "how taint works" above pp_subst() */
-           if (PL_tainting) {
+           if (TAINTING_get) {
                if ((cx->sb_rxtainted & SUBST_TAINT_PAT) ||
                    ((cx->sb_rxtainted & (SUBST_TAINT_STR|SUBST_TAINT_RETAINT))
                                    == (SUBST_TAINT_STR|SUBST_TAINT_RETAINT))
@@ -272,8 +289,10 @@ PP(pp_substcont)
                )
                    SvTAINTED_on(TOPs);  /* taint return value */
                /* needed for mg_set below */
-               PL_tainted = cBOOL(cx->sb_rxtainted &
-                           (SUBST_TAINT_STR|SUBST_TAINT_PAT|SUBST_TAINT_REPL));
+               TAINT_set(
+                    cBOOL(cx->sb_rxtainted &
+                         (SUBST_TAINT_STR|SUBST_TAINT_PAT|SUBST_TAINT_REPL))
+                );
                SvTAINT(TARG);
            }
            /* PL_tainted must be correctly set for this mg_set */
@@ -281,6 +300,7 @@ PP(pp_substcont)
            TAINT_NOT;
            LEAVE_SCOPE(cx->sb_oldsave);
            POPSUBST(cx);
+           PERL_ASYNC_CHECK();
            RETURNOP(pm->op_next);
            assert(0); /* NOTREACHED */
        }
@@ -289,6 +309,7 @@ PP(pp_substcont)
     if (RX_MATCH_COPIED(rx) && RX_SUBBEG(rx) != orig) {
        m = s;
        s = orig;
+        assert(!RX_SUBOFFSET(rx));
        cx->sb_orig = orig = RX_SUBBEG(rx);
        s = orig + (m - s);
        cx->sb_strend = s + (cx->sb_strend - m);
@@ -296,9 +317,9 @@ PP(pp_substcont)
     cx->sb_m = m = RX_OFFS(rx)[0].start + orig;
     if (m > s) {
        if (DO_UTF8(dstr) && !SvUTF8(cx->sb_targ))
-           sv_catpvn_utf8_upgrade(dstr, s, m - s, nsv);
+           sv_catpvn_nomg_utf8_upgrade(dstr, s, m - s, nsv);
        else
-           sv_catpvn(dstr, s, m-s);
+           sv_catpvn_nomg(dstr, s, m-s);
     }
     cx->sb_s = RX_OFFS(rx)[0].end + orig;
     { /* Update the pos() information. */
@@ -321,7 +342,7 @@ PP(pp_substcont)
     /* update the taint state of various various variables in preparation
      * for calling the code block.
      * See "how taint works" above pp_subst() */
-    if (PL_tainting) {
+    if (TAINTING_get) {
        if (RX_MATCH_TAINTED(rx)) /* run time pattern taint, eg locale */
            cx->sb_rxtainted |= SUBST_TAINT_PAT;
 
@@ -352,10 +373,10 @@ Perl_rxres_save(pTHX_ void **rsp, REGEXP *rx)
     PERL_UNUSED_CONTEXT;
 
     if (!p || p[1] < RX_NPARENS(rx)) {
-#ifdef PERL_OLD_COPY_ON_WRITE
-       i = 7 + RX_NPARENS(rx) * 2;
+#ifdef PERL_ANY_COW
+       i = 7 + (RX_NPARENS(rx)+1) * 2;
 #else
-       i = 6 + RX_NPARENS(rx) * 2;
+       i = 6 + (RX_NPARENS(rx)+1) * 2;
 #endif
        if (!p)
            Newx(p, i, UV);
@@ -364,18 +385,20 @@ Perl_rxres_save(pTHX_ void **rsp, REGEXP *rx)
        *rsp = (void*)p;
     }
 
+    /* what (if anything) to free on croak */
     *p++ = PTR2UV(RX_MATCH_COPIED(rx) ? RX_SUBBEG(rx) : NULL);
     RX_MATCH_COPIED_off(rx);
+    *p++ = RX_NPARENS(rx);
 
-#ifdef PERL_OLD_COPY_ON_WRITE
+#ifdef PERL_ANY_COW
     *p++ = PTR2UV(RX_SAVED_COPY(rx));
     RX_SAVED_COPY(rx) = NULL;
 #endif
 
-    *p++ = RX_NPARENS(rx);
-
     *p++ = PTR2UV(RX_SUBBEG(rx));
     *p++ = (UV)RX_SUBLEN(rx);
+    *p++ = (UV)RX_SUBOFFSET(rx);
+    *p++ = (UV)RX_SUBCOFFSET(rx);
     for (i = 0; i <= RX_NPARENS(rx); ++i) {
        *p++ = (UV)RX_OFFS(rx)[i].start;
        *p++ = (UV)RX_OFFS(rx)[i].end;
@@ -394,18 +417,19 @@ S_rxres_restore(pTHX_ void **rsp, REGEXP *rx)
     RX_MATCH_COPY_FREE(rx);
     RX_MATCH_COPIED_set(rx, *p);
     *p++ = 0;
+    RX_NPARENS(rx) = *p++;
 
-#ifdef PERL_OLD_COPY_ON_WRITE
+#ifdef PERL_ANY_COW
     if (RX_SAVED_COPY(rx))
        SvREFCNT_dec (RX_SAVED_COPY(rx));
     RX_SAVED_COPY(rx) = INT2PTR(SV*,*p);
     *p++ = 0;
 #endif
 
-    RX_NPARENS(rx) = *p++;
-
     RX_SUBBEG(rx) = INT2PTR(char*,*p++);
     RX_SUBLEN(rx) = (I32)(*p++);
+    RX_SUBOFFSET(rx) = (I32)*p++;
+    RX_SUBCOFFSET(rx) = (I32)*p++;
     for (i = 0; i <= RX_NPARENS(rx); ++i) {
        RX_OFFS(rx)[i].start = (I32)(*p++);
        RX_OFFS(rx)[i].end = (I32)(*p++);
@@ -421,19 +445,23 @@ S_rxres_free(pTHX_ void **rsp)
     PERL_UNUSED_CONTEXT;
 
     if (p) {
-#ifdef PERL_POISON
        void *tmp = INT2PTR(char*,*p);
-       Safefree(tmp);
-       if (*p)
-           PoisonFree(*p, 1, sizeof(*p));
+#ifdef PERL_POISON
+#ifdef PERL_ANY_COW
+       U32 i = 9 + p[1] * 2;
 #else
-       Safefree(INT2PTR(char*,*p));
+       U32 i = 8 + p[1] * 2;
 #endif
-#ifdef PERL_OLD_COPY_ON_WRITE
-       if (p[1]) {
-           SvREFCNT_dec (INT2PTR(SV*,p[1]));
-       }
 #endif
+
+#ifdef PERL_ANY_COW
+        SvREFCNT_dec (INT2PTR(SV*,p[2]));
+#endif
+#ifdef PERL_POISON
+        PoisonFree(p, i, sizeof(UV));
+#endif
+
+       Safefree(tmp);
        Safefree(p);
        *rsp = NULL;
     }
@@ -445,13 +473,13 @@ S_rxres_free(pTHX_ void **rsp)
 PP(pp_formline)
 {
     dVAR; dSP; dMARK; dORIGMARK;
-    register SV * const tmpForm = *++MARK;
+    SV * const tmpForm = *++MARK;
     SV *formsv;                    /* contains text of original format */
-    register U32 *fpc;     /* format ops program counter */
-    register char *t;      /* current append position in target string */
+    U32 *fpc;      /* format ops program counter */
+    char *t;       /* current append position in target string */
     const char *f;         /* current position in format string */
-    register I32 arg;
-    register SV *sv = NULL; /* current item */
+    I32 arg;
+    SV *sv = NULL; /* current item */
     const char *item = NULL;/* string value of current item */
     I32 itemsize  = 0;     /* length of current item, possibly truncated */
     I32 fieldsize = 0;     /* width of current field */
@@ -1209,7 +1237,7 @@ PP(pp_flop)
        SvGETMAGIC(right);
 
        if (RANGE_IS_NUMERIC(left,right)) {
-           register IV i, j;
+           IV i, j;
            IV max;
            if ((SvOK(left) && SvNV_nomg(left) < IV_MIN) ||
                (SvOK(right) && SvNV_nomg(right) > IV_MAX))
@@ -1293,12 +1321,12 @@ STATIC I32
 S_dopoptolabel(pTHX_ const char *label, STRLEN len, U32 flags)
 {
     dVAR;
-    register I32 i;
+    I32 i;
 
     PERL_ARGS_ASSERT_DOPOPTOLABEL;
 
     for (i = cxstack_ix; i >= 0; i--) {
-       register const PERL_CONTEXT * const cx = &cxstack[i];
+       const PERL_CONTEXT * const cx = &cxstack[i];
        switch (CxTYPE(cx)) {
        case CXt_SUBST:
        case CXt_SUB:
@@ -1410,12 +1438,18 @@ S_dopoptosub_at(pTHX_ const PERL_CONTEXT *cxstk, I32 startingblock)
     PERL_ARGS_ASSERT_DOPOPTOSUB_AT;
 
     for (i = startingblock; i >= 0; i--) {
-       register const PERL_CONTEXT * const cx = &cxstk[i];
+       const PERL_CONTEXT * const cx = &cxstk[i];
        switch (CxTYPE(cx)) {
        default:
            continue;
-       case CXt_EVAL:
        case CXt_SUB:
+            /* in sub foo { /(?{...})/ }, foo ends up on the CX stack
+             * twice; the first for the normal foo() call, and the second
+             * for a faked up re-entry into the sub to execute the
+             * code block. Hide this faked entry from the world. */
+            if (cx->cx_type & CXp_SUB_RE_FAKE)
+                continue;
+       case CXt_EVAL:
        case CXt_FORMAT:
            DEBUG_l( Perl_deb(aTHX_ "(dopoptosub_at(): found sub at cx=%ld)\n", (long)i));
            return i;
@@ -1430,7 +1464,7 @@ S_dopoptoeval(pTHX_ I32 startingblock)
     dVAR;
     I32 i;
     for (i = startingblock; i >= 0; i--) {
-       register const PERL_CONTEXT *cx = &cxstack[i];
+       const PERL_CONTEXT *cx = &cxstack[i];
        switch (CxTYPE(cx)) {
        default:
            continue;
@@ -1448,7 +1482,7 @@ S_dopoptoloop(pTHX_ I32 startingblock)
     dVAR;
     I32 i;
     for (i = startingblock; i >= 0; i--) {
-       register const PERL_CONTEXT * const cx = &cxstack[i];
+       const PERL_CONTEXT * const cx = &cxstack[i];
        switch (CxTYPE(cx)) {
        case CXt_SUBST:
        case CXt_SUB:
@@ -1478,7 +1512,7 @@ S_dopoptogiven(pTHX_ I32 startingblock)
     dVAR;
     I32 i;
     for (i = startingblock; i >= 0; i--) {
-       register const PERL_CONTEXT *cx = &cxstack[i];
+       const PERL_CONTEXT *cx = &cxstack[i];
        switch (CxTYPE(cx)) {
        default:
            continue;
@@ -1506,7 +1540,7 @@ S_dopoptowhen(pTHX_ I32 startingblock)
     dVAR;
     I32 i;
     for (i = startingblock; i >= 0; i--) {
-       register const PERL_CONTEXT *cx = &cxstack[i];
+       const PERL_CONTEXT *cx = &cxstack[i];
        switch (CxTYPE(cx)) {
        default:
            continue;
@@ -1529,7 +1563,7 @@ Perl_dounwind(pTHX_ I32 cxix)
 
     while (cxstack_ix > cxix) {
        SV *sv;
-        register PERL_CONTEXT *cx = &cxstack[cxstack_ix];
+        PERL_CONTEXT *cx = &cxstack[cxstack_ix];
        DEBUG_CX("UNWIND");                                             \
        /* Note: we don't need to restore the base context info till the end. */
        switch (CxTYPE(cx)) {
@@ -1629,6 +1663,11 @@ Perl_die_unwind(pTHX_ SV *msv)
            sv_setsv(ERRSV, exceptsv);
        }
 
+       if (in_eval & EVAL_KEEPERR) {
+           Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "\t(in cleanup) %"SVf,
+                          SVfARG(exceptsv));
+       }
+
        while ((cxix = dopoptoeval(cxstack_ix)) < 0
               && PL_curstackinfo->si_prev)
        {
@@ -1639,7 +1678,7 @@ Perl_die_unwind(pTHX_ SV *msv)
        if (cxix >= 0) {
            I32 optype;
            SV *namesv;
-           register PERL_CONTEXT *cx;
+           PERL_CONTEXT *cx;
            SV **newsp;
            COP *oldcop;
            JMPENV *restartjmpenv;
@@ -1687,13 +1726,8 @@ Perl_die_unwind(pTHX_ SV *msv)
                           SVfARG(exceptsv ? exceptsv : newSVpvs_flags("Unknown error\n",
                                                                     SVs_TEMP)));
            }
-           if (in_eval & EVAL_KEEPERR) {
-               Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "\t(in cleanup) %"SVf,
-                              SVfARG(exceptsv));
-           }
-           else {
+           if (!(in_eval & EVAL_KEEPERR))
                sv_setsv(ERRSV, exceptsv);
-           }
            PL_restartjmpenv = restartjmpenv;
            PL_restartop = restartop;
            JMPENV_JUMP(3);
@@ -1737,9 +1771,9 @@ frame for the sub call itself.
 const PERL_CONTEXT *
 Perl_caller_cx(pTHX_ I32 count, const PERL_CONTEXT **dbcxp)
 {
-    register I32 cxix = dopoptosub(cxstack_ix);
-    register const PERL_CONTEXT *cx;
-    register const PERL_CONTEXT *ccstack = cxstack;
+    I32 cxix = dopoptosub(cxstack_ix);
+    const PERL_CONTEXT *cx;
+    const PERL_CONTEXT *ccstack = cxstack;
     const PERL_SI *top_si = PL_curstackinfo;
 
     for (;;) {
@@ -1779,7 +1813,7 @@ PP(pp_caller)
 {
     dVAR;
     dSP;
-    register const PERL_CONTEXT *cx;
+    const PERL_CONTEXT *cx;
     const PERL_CONTEXT *dbcx;
     I32 gimme;
     const HEK *stash_hek;
@@ -1857,7 +1891,9 @@ PP(pp_caller)
     if (CxTYPE(cx) == CXt_EVAL) {
        /* eval STRING */
        if (CxOLD_OP_TYPE(cx) == OP_ENTEREVAL) {
-           PUSHs(cx->blk_eval.cur_text);
+           PUSHs(newSVpvn_flags(SvPVX(cx->blk_eval.cur_text),
+                                SvCUR(cx->blk_eval.cur_text)-2,
+                                SvUTF8(cx->blk_eval.cur_text)|SVs_TEMP));
            PUSHs(&PL_sv_no);
        }
        /* require */
@@ -1888,17 +1924,15 @@ PP(pp_caller)
        Copy(AvALLOC(ary), AvARRAY(PL_dbargs), AvFILLp(ary) + 1 + off, SV*);
        AvFILLp(PL_dbargs) = AvFILLp(ary) + off;
     }
-    /* XXX only hints propagated via op_private are currently
-     * visible (others are not easily accessible, since they
-     * use the global PL_hints) */
     mPUSHi(CopHINTS_get(cx->blk_oldcop));
     {
        SV * mask ;
        STRLEN * const old_warnings = cx->blk_oldcop->cop_warnings ;
 
-       if  (old_warnings == pWARN_NONE ||
-               (old_warnings == pWARN_STD && (PL_dowarn & G_WARN_ON) == 0))
+       if  (old_warnings == pWARN_NONE)
             mask = newSVpvn(WARN_NONEstring, WARNsize) ;
+       else if (old_warnings == pWARN_STD && (PL_dowarn & G_WARN_ON) == 0)
+            mask = &PL_sv_undef ;
         else if (old_warnings == pWARN_ALL ||
                  (old_warnings == pWARN_STD && PL_dowarn & G_WARN_ON)) {
            /* Get the bit mask for $warnings::Bits{all}, because
@@ -1927,9 +1961,13 @@ PP(pp_reset)
 {
     dVAR;
     dSP;
-    const char * const tmps =
-       (MAXARG < 1 || (!TOPs && !POPs)) ? (const char *)"" : POPpconstx;
-    sv_reset(tmps, CopSTASH(PL_curcop));
+    const char * tmps;
+    STRLEN len = 0;
+    if (MAXARG < 1 || (!TOPs && !POPs))
+       tmps = NULL, len = 0;
+    else
+       tmps = SvPVx_const(POPs, len);
+    sv_resetpvn(tmps, len, CopSTASH(PL_curcop));
     PUSHs(&PL_sv_yes);
     RETURN;
 }
@@ -1950,13 +1988,16 @@ PP(pp_dbstate)
            || SvIV(PL_DBsingle) || SvIV(PL_DBsignal) || SvIV(PL_DBtrace))
     {
        dSP;
-       register PERL_CONTEXT *cx;
+       PERL_CONTEXT *cx;
        const I32 gimme = G_ARRAY;
        U8 hasargs;
        GV * const gv = PL_DBgv;
-       register CV * const cv = GvCV(gv);
+       CV * cv = NULL;
+
+        if (gv && isGV_with_GP(gv))
+            cv = GvCV(gv);
 
-       if (!cv)
+       if (!cv || (!CvROOT(cv) && !CvXSUB(cv)))
            DIE(aTHX_ "No DB::DB routine defined");
 
        if (CvDEPTH(cv) >= 1 && !(PL_debug & DEBUG_DB_RECURSE_FLAG))
@@ -1973,10 +2014,8 @@ PP(pp_dbstate)
        SPAGAIN;
 
        if (CvISXSUB(cv)) {
-           CvDEPTH(cv)++;
            PUSHMARK(SP);
            (void)(*CvXSUB(cv))(aTHX_ cv);
-           CvDEPTH(cv)--;
            FREETMPS;
            LEAVE;
            return NORMAL;
@@ -1986,8 +2025,12 @@ PP(pp_dbstate)
            PUSHSUB_DB(cx);
            cx->blk_sub.retop = PL_op->op_next;
            CvDEPTH(cv)++;
+           if (CvDEPTH(cv) >= 2) {
+               PERL_STACK_OVERFLOW_CHECK();
+               pad_push(CvPADLIST(cv), CvDEPTH(cv));
+           }
            SAVECOMPPAD();
-           PAD_SET_CUR_NOSAVE(CvPADLIST(cv), 1);
+           PAD_SET_CUR_NOSAVE(CvPADLIST(cv), CvDEPTH(cv));
            RETURNOP(CvSTART(cv));
        }
     }
@@ -2037,7 +2080,7 @@ S_adjust_stack_on_leave(pTHX_ SV **newsp, SV **sp, SV **mark, I32 gimme, U32 fla
 PP(pp_enter)
 {
     dVAR; dSP;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
     I32 gimme = GIMME_V;
 
     ENTER_with_name("block");
@@ -2051,7 +2094,7 @@ PP(pp_enter)
 PP(pp_leave)
 {
     dVAR; dSP;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
     SV **newsp;
     PMOP *newpm;
     I32 gimme;
@@ -2077,7 +2120,7 @@ PP(pp_leave)
 PP(pp_enteriter)
 {
     dVAR; dSP; dMARK;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
     const I32 gimme = GIMME_V;
     void *itervar; /* location of the iteration variable */
     U8 cxtype = CXt_LOOP_FOR;
@@ -2200,7 +2243,7 @@ PP(pp_enteriter)
 PP(pp_enterloop)
 {
     dVAR; dSP;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
     const I32 gimme = GIMME_V;
 
     ENTER_with_name("loop1");
@@ -2216,7 +2259,7 @@ PP(pp_enterloop)
 PP(pp_leaveloop)
 {
     dVAR; dSP;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
     I32 gimme;
     SV **newsp;
     PMOP *newpm;
@@ -2353,7 +2396,7 @@ S_return_lvalues(pTHX_ SV **mark, SV **sp, SV **newsp, I32 gimme,
 PP(pp_return)
 {
     dVAR; dSP; dMARK;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
     bool popsub2 = FALSE;
     bool clear_errsv = FALSE;
     bool lval = FALSE;
@@ -2497,7 +2540,7 @@ PP(pp_leavesublv)
     SV **newsp;
     PMOP *newpm;
     I32 gimme;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
     SV *sv;
 
     if (CxMULTICALL(&cxstack[cxstack_ix]))
@@ -2519,38 +2562,60 @@ PP(pp_leavesublv)
     return cx->blk_sub.retop;
 }
 
-PP(pp_last)
+static I32
+S_unwind_loop(pTHX_ const char * const opname)
 {
-    dVAR; dSP;
+    dVAR;
     I32 cxix;
-    register PERL_CONTEXT *cx;
-    I32 pop2 = 0;
-    I32 gimme;
-    I32 optype;
-    OP *nextop = NULL;
-    SV **newsp;
-    PMOP *newpm;
-    SV **mark;
-    SV *sv = NULL;
-
-
     if (PL_op->op_flags & OPf_SPECIAL) {
        cxix = dopoptoloop(cxstack_ix);
        if (cxix < 0)
-           DIE(aTHX_ "Can't \"last\" outside a loop block");
+           /* diag_listed_as: Can't "last" outside a loop block */
+           Perl_croak(aTHX_ "Can't \"%s\" outside a loop block", opname);
     }
     else {
-        cxix = dopoptolabel(cPVOP->op_pv, strlen(cPVOP->op_pv),
-                           (cPVOP->op_private & OPpPV_IS_UTF8) ? SVf_UTF8 : 0);
+       dSP;
+       STRLEN label_len;
+       const char * const label =
+           PL_op->op_flags & OPf_STACKED
+               ? SvPV(TOPs,label_len)
+               : (label_len = strlen(cPVOP->op_pv), cPVOP->op_pv);
+       const U32 label_flags =
+           PL_op->op_flags & OPf_STACKED
+               ? SvUTF8(POPs)
+               : (cPVOP->op_private & OPpPV_IS_UTF8) ? SVf_UTF8 : 0;
+       PUTBACK;
+        cxix = dopoptolabel(label, label_len, label_flags);
        if (cxix < 0)
-           DIE(aTHX_ "Label not found for \"last %"SVf"\"",
-                                        SVfARG(newSVpvn_flags(cPVOP->op_pv,
-                                                    strlen(cPVOP->op_pv),
-                                                    ((cPVOP->op_private & OPpPV_IS_UTF8)
-                                                    ? SVf_UTF8 : 0) | SVs_TEMP)));
+           /* diag_listed_as: Label not found for "last %s" */
+           Perl_croak(aTHX_ "Label not found for \"%s %"SVf"\"",
+                                      opname,
+                                       SVfARG(PL_op->op_flags & OPf_STACKED
+                                              && !SvGMAGICAL(TOPp1s)
+                                              ? TOPp1s
+                                              : newSVpvn_flags(label,
+                                                    label_len,
+                                                    label_flags | SVs_TEMP)));
     }
     if (cxix < cxstack_ix)
        dounwind(cxix);
+    return cxix;
+}
+
+PP(pp_last)
+{
+    dVAR;
+    PERL_CONTEXT *cx;
+    I32 pop2 = 0;
+    I32 gimme;
+    I32 optype;
+    OP *nextop = NULL;
+    SV **newsp;
+    PMOP *newpm;
+    SV **mark;
+    SV *sv = NULL;
+
+    S_unwind_loop(aTHX_ "last");
 
     POPBLOCK(cx,newpm);
     cxstack_ix++; /* temporarily protect top context */
@@ -2581,9 +2646,8 @@ PP(pp_last)
     }
 
     TAINT_NOT;
-    SP = adjust_stack_on_leave(newsp, SP, MARK, gimme,
+    PL_stack_sp = adjust_stack_on_leave(newsp, PL_stack_sp, MARK, gimme,
                                pop2 == CXt_SUB ? SVs_TEMP : 0);
-    PUTBACK;
 
     LEAVE;
     cxstack_ix--;
@@ -2611,65 +2675,29 @@ PP(pp_last)
 PP(pp_next)
 {
     dVAR;
-    I32 cxix;
-    register PERL_CONTEXT *cx;
-    I32 inner;
+    PERL_CONTEXT *cx;
+    const I32 inner = PL_scopestack_ix;
 
-    if (PL_op->op_flags & OPf_SPECIAL) {
-       cxix = dopoptoloop(cxstack_ix);
-       if (cxix < 0)
-           DIE(aTHX_ "Can't \"next\" outside a loop block");
-    }
-    else {
-       cxix = dopoptolabel(cPVOP->op_pv, strlen(cPVOP->op_pv),
-                           (cPVOP->op_private & OPpPV_IS_UTF8) ? SVf_UTF8 : 0);
-       if (cxix < 0)
-           DIE(aTHX_ "Label not found for \"next %"SVf"\"",
-                                        SVfARG(newSVpvn_flags(cPVOP->op_pv, 
-                                                    strlen(cPVOP->op_pv),
-                                                    ((cPVOP->op_private & OPpPV_IS_UTF8)
-                                                    ? SVf_UTF8 : 0) | SVs_TEMP)));
-    }
-    if (cxix < cxstack_ix)
-       dounwind(cxix);
+    S_unwind_loop(aTHX_ "next");
 
     /* clear off anything above the scope we're re-entering, but
      * save the rest until after a possible continue block */
-    inner = PL_scopestack_ix;
     TOPBLOCK(cx);
     if (PL_scopestack_ix < inner)
        leave_scope(PL_scopestack[PL_scopestack_ix]);
     PL_curcop = cx->blk_oldcop;
+    PERL_ASYNC_CHECK();
     return (cx)->blk_loop.my_op->op_nextop;
 }
 
 PP(pp_redo)
 {
     dVAR;
-    I32 cxix;
-    register PERL_CONTEXT *cx;
+    const I32 cxix = S_unwind_loop(aTHX_ "redo");
+    PERL_CONTEXT *cx;
     I32 oldsave;
-    OP* redo_op;
+    OP* redo_op = cxstack[cxix].blk_loop.my_op->op_redoop;
 
-    if (PL_op->op_flags & OPf_SPECIAL) {
-       cxix = dopoptoloop(cxstack_ix);
-       if (cxix < 0)
-           DIE(aTHX_ "Can't \"redo\" outside a loop block");
-    }
-    else {
-       cxix = dopoptolabel(cPVOP->op_pv, strlen(cPVOP->op_pv),
-                           (cPVOP->op_private & OPpPV_IS_UTF8) ? SVf_UTF8 : 0);
-       if (cxix < 0)
-           DIE(aTHX_ "Label not found for \"redo %"SVf"\"",
-                                        SVfARG(newSVpvn_flags(cPVOP->op_pv,
-                                                    strlen(cPVOP->op_pv),
-                                                    ((cPVOP->op_private & OPpPV_IS_UTF8)
-                                                    ? SVf_UTF8 : 0) | SVs_TEMP)));
-    }
-    if (cxix < cxstack_ix)
-       dounwind(cxix);
-
-    redo_op = cxstack[cxix].blk_loop.my_op->op_redoop;
     if (redo_op->op_type == OP_ENTER) {
        /* pop one less context to avoid $x being freed in while (my $x..) */
        cxstack_ix++;
@@ -2682,6 +2710,7 @@ PP(pp_redo)
     LEAVE_SCOPE(oldsave);
     FREETMPS;
     PL_curcop = cx->blk_oldcop;
+    PERL_ASYNC_CHECK();
     return redo_op;
 }
 
@@ -2690,12 +2719,12 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac
 {
     dVAR;
     OP **ops = opstack;
-    static const char too_deep[] = "Target of goto is too deeply nested";
+    static const char* const too_deep = "Target of goto is too deeply nested";
 
     PERL_ARGS_ASSERT_DOFINDLABEL;
 
     if (ops >= oplimit)
-       Perl_croak(aTHX_ too_deep);
+       Perl_croak(aTHX_ "%s", too_deep);
     if (o->op_type == OP_LEAVE ||
        o->op_type == OP_SCOPE ||
        o->op_type == OP_LEAVELOOP ||
@@ -2704,7 +2733,7 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac
     {
        *ops++ = cUNOPo->op_first;
        if (ops >= oplimit)
-           Perl_croak(aTHX_ too_deep);
+           Perl_croak(aTHX_ "%s", too_deep);
     }
     *ops = 0;
     if (o->op_flags & OPf_KIDS) {
@@ -2755,27 +2784,26 @@ PP(pp_goto)
     dVAR; dSP;
     OP *retop = NULL;
     I32 ix;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
 #define GOTO_DEPTH 64
     OP *enterops[GOTO_DEPTH];
     const char *label = NULL;
     STRLEN label_len = 0;
     U32 label_flags = 0;
     const bool do_dump = (PL_op->op_type == OP_DUMP);
-    static const char must_have_label[] = "goto must have label";
+    static const char* const must_have_label = "goto must have label";
 
     if (PL_op->op_flags & OPf_STACKED) {
        SV * const sv = POPs;
+       SvGETMAGIC(sv);
 
        /* This egregious kludge implements goto &subroutine */
        if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVCV) {
            I32 cxix;
-           register PERL_CONTEXT *cx;
+           PERL_CONTEXT *cx;
            CV *cv = MUTABLE_CV(SvRV(sv));
-           SV** mark;
-           I32 items = 0;
+           AV *arg = GvAV(PL_defgv);
            I32 oldsave;
-           bool reified = 0;
 
        retry:
            if (!CvROOT(cv) && !CvXSUB(cv)) {
@@ -2802,14 +2830,18 @@ PP(pp_goto)
            SvREFCNT_inc_simple_void(cv); /* avoid premature free during unwind */
            FREETMPS;
            cxix = dopoptosub(cxstack_ix);
-           if (cxix < 0)
-               DIE(aTHX_ "Can't goto subroutine outside a subroutine");
-           if (cxix < cxstack_ix)
+           if (cxix < cxstack_ix) {
+                if (cxix < 0) {
+                    SvREFCNT_dec(cv);
+                    DIE(aTHX_ "Can't goto subroutine outside a subroutine");
+                }
                dounwind(cxix);
+            }
            TOPBLOCK(cx);
            SPAGAIN;
            /* ban goto in eval: see <20050521150056.GC20213@iabyn.com> */
            if (CxTYPE(cx) == CXt_EVAL) {
+               SvREFCNT_dec(cv);
                if (CxREALEVAL(cx))
                /* diag_listed_as: Can't goto subroutine from an eval-%s */
                    DIE(aTHX_ "Can't goto subroutine from an eval-string");
@@ -2818,35 +2850,25 @@ PP(pp_goto)
                    DIE(aTHX_ "Can't goto subroutine from an eval-block");
            }
            else if (CxMULTICALL(cx))
+           {
+               SvREFCNT_dec(cv);
                DIE(aTHX_ "Can't goto subroutine from a sort sub (or similar callback)");
+           }
            if (CxTYPE(cx) == CXt_SUB && CxHASARGS(cx)) {
-               /* put @_ back onto stack */
                AV* av = cx->blk_sub.argarray;
 
-               items = AvFILLp(av) + 1;
-               EXTEND(SP, items+1); /* @_ could have been extended. */
-               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)) {
-                   reified = 1;
+               /* abandon the original @_ if it got reified or if it is
+                  the same as the current @_ */
+               if (AvREAL(av) || av == arg) {
                    SvREFCNT_dec(av);
                    av = newAV();
-                   av_extend(av, items-1);
                    AvREIFY_only(av);
                    PAD_SVl(0) = MUTABLE_SV(cx->blk_sub.argarray = av);
                }
+               else CLEAR_ARGARRAY(av);
            }
-           else if (CvISXSUB(cv)) {    /* put GvAV(defgv) back onto stack */
-               AV* const av = GvAV(PL_defgv);
-               items = AvFILLp(av) + 1;
-               EXTEND(SP, items+1); /* @_ could have been extended. */
-               Copy(AvARRAY(av), SP + 1, items, SV*);
-           }
-           mark = SP;
-           SP += items;
+           /* We donate this refcount later to the callee’s pad. */
+           SvREFCNT_inc_simple_void(arg);
            if (CxTYPE(cx) == CXt_SUB &&
                !(CvDEPTH(cx->blk_sub.cv) = cx->blk_sub.olddepth))
                SvREFCNT_dec(cx->blk_sub.cv);
@@ -2857,6 +2879,7 @@ PP(pp_goto)
             * our precious cv.  See bug #99850. */
            if (!CvROOT(cv) && !CvXSUB(cv)) {
                const GV * const gv = CvGV(cv);
+               SvREFCNT_dec(arg);
                if (gv) {
                    SV * const tmpstr = sv_newmortal();
                    gv_efullname3(tmpstr, gv, NULL);
@@ -2871,12 +2894,30 @@ PP(pp_goto)
            SAVEFREESV(cv); /* later, undo the 'avoid premature free' hack */
            if (CvISXSUB(cv)) {
                OP* const retop = cx->blk_sub.retop;
-               SV **newsp PERL_UNUSED_DECL;
-               I32 gimme PERL_UNUSED_DECL;
-               if (reified) {
+               SV **newsp;
+               I32 gimme;
+               const SSize_t items = AvFILLp(arg) + 1;
+               SV** mark;
+
+                PERL_UNUSED_VAR(newsp);
+                PERL_UNUSED_VAR(gimme);
+
+               /* put GvAV(defgv) back onto stack */
+               EXTEND(SP, items+1); /* @_ could have been extended. */
+               Copy(AvARRAY(arg), SP + 1, items, SV*);
+               mark = SP;
+               SP += items;
+               if (AvREAL(arg)) {
                    I32 index;
                    for (index=0; index<items; index++)
-                       sv_2mortal(SP[-index]);
+                       SvREFCNT_inc_void(sv_2mortal(SP[-index]));
+               }
+               SvREFCNT_dec(arg);
+               if (CxTYPE(cx) == CXt_SUB && CxHASARGS(cx)) {
+                   /* Restore old @_ */
+                   arg = GvAV(PL_defgv);
+                   GvAV(PL_defgv) = cx->blk_sub.savearray;
+                   SvREFCNT_dec(arg);
                }
 
                /* XS subs don't have a CxSUB, so pop it */
@@ -2886,15 +2927,11 @@ PP(pp_goto)
                PUTBACK;
                (void)(*CvXSUB(cv))(aTHX_ cv);
                LEAVE;
+               PERL_ASYNC_CHECK();
                return retop;
            }
            else {
-               AV* const padlist = CvPADLIST(cv);
-               if (CxTYPE(cx) == CXt_EVAL) {
-                   PL_in_eval = CxOLD_IN_EVAL(cx);
-                   PL_eval_root = cx->blk_eval.old_eval_root;
-                   cx->cx_type = CXt_SUB;
-               }
+               PADLIST * const padlist = CvPADLIST(cv);
                cx->blk_sub.cv = cv;
                cx->blk_sub.olddepth = CvDEPTH(cv);
 
@@ -2911,41 +2948,26 @@ PP(pp_goto)
                PAD_SET_CUR_NOSAVE(padlist, CvDEPTH(cv));
                if (CxHASARGS(cx))
                {
-                   AV *const av = MUTABLE_AV(PAD_SVl(0));
-
-                   cx->blk_sub.savearray = GvAV(PL_defgv);
-                   GvAV(PL_defgv) = MUTABLE_AV(SvREFCNT_inc_simple(av));
                    CX_CURPAD_SAVE(cx->blk_sub);
-                   cx->blk_sub.argarray = av;
 
-                   if (items >= AvMAX(av) + 1) {
-                       SV **ary = AvALLOC(av);
-                       if (AvARRAY(av) != ary) {
-                           AvMAX(av) += AvARRAY(av) - AvALLOC(av);
-                           AvARRAY(av) = ary;
-                       }
-                       if (items >= AvMAX(av) + 1) {
-                           AvMAX(av) = items - 1;
-                           Renew(ary,items+1,SV*);
-                           AvALLOC(av) = ary;
-                           AvARRAY(av) = ary;
-                       }
-                   }
-                   ++mark;
-                   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);
-                       mark++;
+                   /* cx->blk_sub.argarray has no reference count, so we
+                      need something to hang on to our argument array so
+                      that cx->blk_sub.argarray does not end up pointing
+                      to freed memory as the result of undef *_.  So put
+                      it in the callee’s pad, donating our refer-
+                      ence count. */
+                   SvREFCNT_dec(PAD_SVl(0));
+                   PAD_SVl(0) = (SV *)(cx->blk_sub.argarray = arg);
+
+                   /* GvAV(PL_defgv) might have been modified on scope
+                      exit, so restore it. */
+                   if (arg != GvAV(PL_defgv)) {
+                       AV * const av = GvAV(PL_defgv);
+                       GvAV(PL_defgv) = (AV *)SvREFCNT_inc_simple(arg);
+                       SvREFCNT_dec(av);
                    }
                }
+               else SvREFCNT_dec(arg);
                if (PERLDB_SUB) {       /* Checking curstash breaks DProf. */
                    Perl_get_db_sub(aTHX_ NULL, cv);
                    if (PERLDB_GOTO) {
@@ -2957,11 +2979,12 @@ PP(pp_goto)
                        }
                    }
                }
+               PERL_ASYNC_CHECK();
                RETURNOP(CvSTART(cv));
            }
        }
        else {
-           label       = SvPV_const(sv, label_len);
+           label       = SvPV_nomg_const(sv, label_len);
             label_flags = SvUTF8(sv);
        }
     }
@@ -2970,7 +2993,7 @@ PP(pp_goto)
         label_flags = (cPVOP->op_private & OPpPV_IS_UTF8) ? SVf_UTF8 : 0;
         label_len   = strlen(label);
     }
-    if (!(do_dump || label_len)) DIE(aTHX_ must_have_label);
+    if (!(do_dump || label_len)) DIE(aTHX_ "%s", must_have_label);
 
     PERL_ASYNC_CHECK();
 
@@ -3112,6 +3135,7 @@ PP(pp_goto)
        PL_do_undump = FALSE;
     }
 
+    PERL_ASYNC_CHECK();
     RETURNOP(retop);
 }
 
@@ -3245,15 +3269,16 @@ than in the scope of the debugger itself).
 CV*
 Perl_find_runcv(pTHX_ U32 *db_seqp)
 {
-    return Perl_find_runcv_where(aTHX_ 0, NULL, db_seqp);
+    return Perl_find_runcv_where(aTHX_ 0, 0, db_seqp);
 }
 
 /* If this becomes part of the API, it might need a better name. */
 CV *
-Perl_find_runcv_where(pTHX_ U8 cond, void *arg, U32 *db_seqp)
+Perl_find_runcv_where(pTHX_ U8 cond, IV arg, U32 *db_seqp)
 {
     dVAR;
     PERL_SI     *si;
+    int                 level = 0;
 
     if (db_seqp)
        *db_seqp = PL_curcop->cop_seq;
@@ -3269,13 +3294,20 @@ Perl_find_runcv_where(pTHX_ U8 cond, void *arg, U32 *db_seqp)
                    *db_seqp = cx->blk_oldcop->cop_seq;
                    continue;
                }
+                if (cx->cx_type & CXp_SUB_RE)
+                    continue;
            }
            else if (CxTYPE(cx) == CXt_EVAL && !CxTRYBLOCK(cx))
                cv = cx->blk_eval.cv;
            if (cv) {
                switch (cond) {
-               case FIND_RUNCV_root_eq:
-                   if (CvROOT(cv) != (OP *)arg) continue;
+               case FIND_RUNCV_padid_eq:
+                   if (!CvPADLIST(cv)
+                    || PadlistNAMES(CvPADLIST(cv)) != INT2PTR(PADNAMELIST *, arg))
+                       continue;
+                   return cv;
+               case FIND_RUNCV_level_eq:
+                   if (level++ != arg) continue;
                    /* GERONIMO! */
                default:
                    return cv;
@@ -3283,7 +3315,7 @@ Perl_find_runcv_where(pTHX_ U8 cond, void *arg, U32 *db_seqp)
            }
        }
     }
-    return cond == FIND_RUNCV_root_eq ? NULL : PL_main_cv;
+    return cond == FIND_RUNCV_padid_eq ? NULL : PL_main_cv;
 }
 
 
@@ -3343,7 +3375,9 @@ S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh)
 
     PL_in_eval = (in_require
                  ? (EVAL_INREQUIRE | (PL_in_eval & EVAL_INEVAL))
-                 : EVAL_INEVAL);
+                 : (EVAL_INEVAL |
+                        ((PL_op->op_private & OPpEVAL_RE_REPARSING)
+                            ? EVAL_RE_REPARSING : 0)));
 
     PUSHMARK(SP);
 
@@ -3405,6 +3439,15 @@ S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh)
     else {
        PL_hints = saveop->op_private & OPpEVAL_COPHH
                     ? oldcurcop->cop_hints : saveop->op_targ;
+
+        /* making 'use re eval' not be in scope when compiling the
+         * qr/mabye_has_runtime_code_block/ ensures that we don't get
+         * infinite recursion when S_has_runtime_code() gives a false
+         * positive: the second time round, HINT_RE_EVAL isn't set so we
+         * don't bother calling S_has_runtime_code() */
+        if (PL_in_eval & EVAL_RE_REPARSING)
+            PL_hints &= ~HINT_RE_EVAL;
+
        if (hh) {
            /* SAVEHINTS created a new HV in PL_hintgv, which we need to GC */
            SvREFCNT_dec(GvHV(PL_hintgv));
@@ -3449,6 +3492,7 @@ S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh)
        PERL_CONTEXT *cx;
        I32 optype;                     /* Used by POPEVAL. */
        SV *namesv;
+        SV *errsv = NULL;
 
        cx = NULL;
        namesv = NULL;
@@ -3460,7 +3504,6 @@ S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh)
        PL_op = saveop;
        if (yystatus != 3) {
            if (PL_eval_root) {
-               cv_forget_slab(evalcv);
                op_free(PL_eval_root);
                PL_eval_root = NULL;
            }
@@ -3472,6 +3515,7 @@ S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh)
            LEAVE_with_name("eval"); /* pp_entereval knows about this LEAVE.  */
        }
 
+       errsv = ERRSV;
        if (in_require) {
            if (!cx) {
                /* If cx is still NULL, it means that we didn't go in the
@@ -3485,13 +3529,13 @@ S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh)
                            SvUTF8(namesv) ? -(I32)SvCUR(namesv) : (I32)SvCUR(namesv),
                           &PL_sv_undef, 0);
            Perl_croak(aTHX_ "%"SVf"Compilation failed in require",
-                      SVfARG(ERRSV
-                                ? ERRSV
+                      SVfARG(errsv
+                                ? errsv
                                 : newSVpvs_flags("Unknown error\n", SVs_TEMP)));
        }
        else {
-           if (!*(SvPVx_nolen_const(ERRSV))) {
-               sv_setpvs(ERRSV, "Compilation error");
+           if (!*(SvPV_nolen_const(errsv))) {
+               sv_setpvs(errsv, "Compilation error");
            }
        }
        if (gimme != G_ARRAY) PUSHs(&PL_sv_undef);
@@ -3584,7 +3628,7 @@ S_doopen_pm(pTHX_ SV *name)
 PP(pp_require)
 {
     dVAR; dSP;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
     SV *sv;
     const char *name;
     STRLEN len;
@@ -3592,6 +3636,9 @@ PP(pp_require)
     STRLEN unixlen;
 #ifdef VMS
     int vms_unixname = 0;
+    char *unixnamebuf;
+    char *unixdir;
+    char *unixdirbuf;
 #endif
     const char *tryname = NULL;
     SV *namesv = NULL;
@@ -3609,7 +3656,7 @@ PP(pp_require)
     sv = POPs;
     if ( (SvNIOKp(sv) || SvVOK(sv)) && PL_op->op_type != OP_DOFILE) {
        sv = sv_2mortal(new_version(sv));
-       if (!sv_derived_from(PL_patchlevel, "version"))
+       if (!Perl_sv_derived_from_pvn(aTHX_ PL_patchlevel, STR_WITH_LEN("version"), 0))
            upg_version(PL_patchlevel, TRUE);
        if (cUNOP->op_first->op_type == OP_CONST && cUNOP->op_first->op_private & OPpCONST_NOVER) {
            if ( vcmp(sv,PL_patchlevel) <= 0 )
@@ -3677,7 +3724,9 @@ PP(pp_require)
      * To prevent this, the key must be stored in UNIX format if the VMS
      * name can be translated to UNIX.
      */
-    if ((unixname = tounixspec(name, NULL)) != NULL) {
+    
+    if ((unixnamebuf = SvPVX(sv_2mortal(newSVpv("", VMS_MAXRSS-1))))
+        && (unixname = tounixspec(name, unixnamebuf)) != NULL) {
        unixlen = strlen(unixname);
        vms_unixname = 1;
     }
@@ -3702,6 +3751,8 @@ PP(pp_require)
        }
     }
 
+    LOADING_FILE_PROBE(unixname);
+
     /* prepare to compile file */
 
     if (path_is_absolute(name)) {
@@ -3852,8 +3903,8 @@ PP(pp_require)
                    }
 
 #ifdef VMS
-                   char *unixdir;
-                   if ((unixdir = tounixpath(dir, NULL)) == NULL)
+                   if (((unixdirbuf = SvPVX(sv_2mortal(newSVpv("", VMS_MAXRSS-1)))) == NULL)
+                       || ((unixdir = tounixpath(dir, unixdirbuf)) == NULL))
                        continue;
                    sv_setpv(namesv, unixdir);
                    sv_catpv(namesv, unixname);
@@ -3881,7 +3932,12 @@ PP(pp_require)
 
                        memcpy(tmp, dir, dirlen);
                        tmp +=dirlen;
-                       *tmp++ = '/';
+
+                       /* Avoid '<dir>//<file>' */
+                       if (!dirlen || *(tmp-1) != '/') {
+                           *tmp++ = '/';
+                       }
+
                        /* name came from an SV, so it will have a '\0' at the
                           end that we can copy as part of this memcpy().  */
                        memcpy(tmp, name, len + 1);
@@ -3897,7 +3953,7 @@ PP(pp_require)
                    if (tryrsfp) {
                        if (tryname[0] == '.' && tryname[1] == '/') {
                            ++tryname;
-                           while (*++tryname == '/');
+                           while (*++tryname == '/') {}
                        }
                        break;
                    }
@@ -3925,22 +3981,36 @@ PP(pp_require)
                if (namesv) {                   /* did we lookup @INC? */
                    AV * const ar = GvAVn(PL_incgv);
                    I32 i;
+                   SV *const msg = newSVpvs_flags("", SVs_TEMP);
                    SV *const inc = newSVpvs_flags("", SVs_TEMP);
                    for (i = 0; i <= AvFILL(ar); i++) {
                        sv_catpvs(inc, " ");
                        sv_catsv(inc, *av_fetch(ar, i, TRUE));
                    }
+                   if (len >= 4 && memEQ(name + len - 3, ".pm", 4)) {
+                       const char *c, *e = name + len - 3;
+                       sv_catpv(msg, " (you may need to install the ");
+                       for (c = name; c < e; c++) {
+                           if (*c == '/') {
+                               sv_catpvn(msg, "::", 2);
+                           }
+                           else {
+                               sv_catpvn(msg, c, 1);
+                           }
+                       }
+                       sv_catpv(msg, " module)");
+                   }
+                   else if (len >= 2 && memEQ(name + len - 2, ".h", 3)) {
+                       sv_catpv(msg, " (change .h to .ph maybe?) (did you run h2ph?)");
+                   }
+                   else if (len >= 3 && memEQ(name + len - 3, ".ph", 4)) {
+                       sv_catpv(msg, " (did you run h2ph?)");
+                   }
 
                    /* diag_listed_as: Can't locate %s */
                    DIE(aTHX_
-                       "Can't locate %s in @INC%s%s (@INC contains:%" SVf ")",
-                       name,
-                       (memEQ(name + len - 2, ".h", 3)
-                        ? " (change .h to .ph maybe?) (did you run h2ph?)" : ""),
-                       (memEQ(name + len - 3, ".ph", 4)
-                        ? " (did you run h2ph?)" : ""),
-                       inc
-                       );
+                       "Can't locate %s in @INC%" SVf " (@INC contains:%" SVf ")",
+                       name, msg, inc);
                }
            }
            DIE(aTHX_ "Can't locate %s", name);
@@ -4004,6 +4074,8 @@ PP(pp_require)
     /* Restore encoding. */
     PL_encoding = encoding;
 
+    LOADED_FILE_PROBE(unixname);
+
     return op;
 }
 
@@ -4023,7 +4095,7 @@ PP(pp_hintseval)
 PP(pp_entereval)
 {
     dVAR; dSP;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
     SV *sv;
     const I32 gimme = GIMME_V;
     const U32 was = PL_breakable_sub_gen;
@@ -4154,7 +4226,7 @@ PP(pp_leaveeval)
     SV **newsp;
     PMOP *newpm;
     I32 gimme;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
     OP *retop;
     const U8 save_flags = PL_op -> op_flags;
     I32 optype;
@@ -4208,7 +4280,7 @@ Perl_delete_eval_scope(pTHX)
     SV **newsp;
     PMOP *newpm;
     I32 gimme;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
     I32 optype;
        
     POPBLOCK(cx,newpm);
@@ -4259,7 +4331,7 @@ PP(pp_leavetry)
     SV **newsp;
     PMOP *newpm;
     I32 gimme;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
     I32 optype;
 
     PERL_ASYNC_CHECK();
@@ -4279,14 +4351,21 @@ PP(pp_leavetry)
 PP(pp_entergiven)
 {
     dVAR; dSP;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
     const I32 gimme = GIMME_V;
     
     ENTER_with_name("given");
     SAVETMPS;
 
-    SAVECLEARSV(PAD_SVl(PL_op->op_targ));
-    sv_setsv_mg(PAD_SV(PL_op->op_targ), POPs);
+    if (PL_op->op_targ) {
+       SAVEPADSVANDMORTALIZE(PL_op->op_targ);
+       SvREFCNT_dec(PAD_SVl(PL_op->op_targ));
+       PAD_SVl(PL_op->op_targ) = SvREFCNT_inc_NN(POPs);
+    }
+    else {
+       SAVE_DEFSV;
+       DEFSV_set(POPs);
+    }
 
     PUSHBLOCK(cx, CXt_GIVEN, SP);
     PUSHGIVEN(cx);
@@ -4297,7 +4376,7 @@ PP(pp_entergiven)
 PP(pp_leavegiven)
 {
     dVAR; dSP;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
     I32 gimme;
     SV **newsp;
     PMOP *newpm;
@@ -4845,7 +4924,7 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied)
 PP(pp_enterwhen)
 {
     dVAR; dSP;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
     const I32 gimme = GIMME_V;
 
     /* This is essentially an optimization: if the match
@@ -4870,7 +4949,7 @@ PP(pp_leavewhen)
 {
     dVAR; dSP;
     I32 cxix;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
     I32 gimme;
     SV **newsp;
     PMOP *newpm;
@@ -4904,17 +4983,20 @@ PP(pp_leavewhen)
            leave_scope(PL_scopestack[PL_scopestack_ix]);
        PL_curcop = cx->blk_oldcop;
 
+       PERL_ASYNC_CHECK();
        return cx->blk_loop.my_op->op_nextop;
     }
-    else
+    else {
+       PERL_ASYNC_CHECK();
        RETURNOP(cx->blk_givwhen.leave_op);
+    }
 }
 
 PP(pp_continue)
 {
     dVAR; dSP;
     I32 cxix;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
     I32 gimme;
     SV **newsp;
     PMOP *newpm;
@@ -4942,7 +5024,7 @@ PP(pp_break)
 {
     dVAR;   
     I32 cxix;
-    register PERL_CONTEXT *cx;
+    PERL_CONTEXT *cx;
 
     cxix = dopoptogiven(cxstack_ix); 
     if (cxix < 0)
@@ -4965,17 +5047,17 @@ static MAGIC *
 S_doparseform(pTHX_ SV *sv)
 {
     STRLEN len;
-    register char *s = SvPV(sv, len);
-    register char *send;
-    register char *base = NULL; /* start of current field */
-    register I32 skipspaces = 0; /* number of contiguous spaces seen */
+    char *s = SvPV(sv, len);
+    char *send;
+    char *base = NULL; /* start of current field */
+    I32 skipspaces = 0; /* number of contiguous spaces seen */
     bool noblank   = FALSE; /* ~ or ~~ seen on this line */
     bool repeat    = FALSE; /* ~~ seen on this line */
     bool postspace = FALSE; /* a text field may need right padding */
     U32 *fops;
-    register U32 *fpc;
+    U32 *fpc;
     U32 *linepc = NULL;            /* position of last FF_LINEMARK */
-    register I32 arg;
+    I32 arg;
     bool ischop;           /* it's a ^ rather than a @ */
     bool unchopnum = FALSE; /* at least one @ (i.e. non-chop) num field seen */
     int maxops = 12; /* FF_LINEMARK + FF_END + 10 (\0 without preceding \n) */
@@ -5342,8 +5424,10 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
            if (SvOK(out)) {
                status = SvIV(out);
            }
-            else if (SvTRUE(ERRSV)) {
-                err = newSVsv(ERRSV);
+            else {
+                SV * const errsv = ERRSV;
+                if (SvTRUE_NN(errsv))
+                    err = newSVsv(errsv);
             }
        }
 
@@ -5352,6 +5436,7 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
        LEAVE_with_name("call_filter_sub");
     }
 
+    if (SvIsCOW(upstream)) sv_force_normal(upstream);
     if(!err && SvOK(upstream)) {
        got_p = SvPV(upstream, got_len);
        if (umaxlen) {