This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #107000] Don’t leak if hh copying dies
[perl5.git] / mg.c
diff --git a/mg.c b/mg.c
index f4979f1..cbae421 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -213,6 +213,10 @@ Perl_mg_get(pTHX_ SV *sv)
            if (mg->mg_flags & MGf_GSKIP)
                (SSPTR(mgs_ix, MGS *))->mgs_magical = 0;
        }
+       else if (vtbl == &PL_vtbl_utf8) {
+           /* get-magic can reallocate the PV */
+           magic_setutf8(sv, mg);
+       }
 
        mg = nextmg;
 
@@ -612,7 +616,7 @@ Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg)
     PERL_ARGS_ASSERT_MAGIC_REGDATA_CNT;
 
     if (PL_curpm) {
-       register const REGEXP * const rx = PM_GETRE(PL_curpm);
+       const REGEXP * const rx = PM_GETRE(PL_curpm);
        if (rx) {
            if (mg->mg_obj) {                   /* @+ */
                /* return the number possible */
@@ -633,6 +637,8 @@ Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg)
     return (U32)-1;
 }
 
+/* @-, @+ */
+
 int
 Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg)
 {
@@ -641,18 +647,18 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg)
     PERL_ARGS_ASSERT_MAGIC_REGDATUM_GET;
 
     if (PL_curpm) {
-       register const REGEXP * const rx = PM_GETRE(PL_curpm);
+       const REGEXP * const rx = PM_GETRE(PL_curpm);
        if (rx) {
-           register const I32 paren = mg->mg_len;
-           register I32 s;
-           register I32 t;
+           const I32 paren = mg->mg_len;
+           I32 s;
+           I32 t;
            if (paren < 0)
                return 0;
            if (paren <= (I32)RX_NPARENS(rx) &&
                (s = RX_OFFS(rx)[paren].start) != -1 &&
                (t = RX_OFFS(rx)[paren].end) != -1)
                {
-                   register I32 i;
+                   I32 i;
                    if (mg->mg_obj)             /* @+ */
                        i = t;
                    else                        /* @- */
@@ -661,7 +667,9 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg)
                    if (i > 0 && RX_MATCH_UTF8(rx)) {
                        const char * const b = RX_SUBBEG(rx);
                        if (b)
-                           i = utf8_length((U8*)b, (U8*)(b+i));
+                           i = RX_SUBCOFFSET(rx) +
+                                    utf8_length((U8*)b,
+                                        (U8*)(b-RX_SUBOFFSET(rx)+i));
                    }
 
                    sv_setiv(sv, i);
@@ -671,6 +679,8 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg)
     return 0;
 }
 
+/* @-, @+ */
+
 int
 Perl_magic_regdatum_set(pTHX_ SV *sv, MAGIC *mg)
 {
@@ -685,9 +695,9 @@ U32
 Perl_magic_len(pTHX_ SV *sv, MAGIC *mg)
 {
     dVAR;
-    register I32 paren;
-    register I32 i;
-    register const REGEXP * rx;
+    I32 paren;
+    I32 i;
+    const REGEXP * rx;
     const char * const remaining = mg->mg_ptr + 1;
 
     PERL_ARGS_ASSERT_MAGIC_LEN;
@@ -804,9 +814,9 @@ int
 Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
 {
     dVAR;
-    register I32 paren;
-    register const char *s = NULL;
-    register REGEXP *rx;
+    I32 paren;
+    const char *s = NULL;
+    REGEXP *rx;
     const char * const remaining = mg->mg_ptr + 1;
     const char nextchar = *remaining;
 
@@ -814,7 +824,8 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
 
     switch (*mg->mg_ptr) {
     case '\001':               /* ^A */
-       sv_setsv(sv, PL_bodytarget);
+       if (SvOK(PL_bodytarget)) sv_copypv(sv, PL_bodytarget);
+       else sv_setsv(sv, &PL_sv_undef);
        if (SvTAINTED(PL_bodytarget))
            SvTAINTED_on(sv);
        break;
@@ -895,6 +906,20 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
     case '\011':               /* ^I */ /* NOT \t in EBCDIC */
        sv_setpv(sv, PL_inplace); /* Will undefine sv if PL_inplace is NULL */
        break;
+    case '\014':               /* ^LAST_FH */
+       if (strEQ(remaining, "AST_FH")) {
+           if (PL_last_in_gv) {
+               assert(isGV_with_GP(PL_last_in_gv));
+               SV_CHECK_THINKFIRST_COW_DROP(sv);
+               prepare_SV_for_RV(sv);
+               SvOK_off(sv);
+               SvRV_set(sv, SvREFCNT_inc_simple_NN(PL_last_in_gv));
+               SvROK_on(sv);
+               sv_rvweaken(sv);
+           }
+           else sv_setsv_nomg(sv, NULL);
+       }
+       break;
     case '\017':               /* ^O & ^OPEN */
        if (nextchar == '\0') {
            sv_setpv(sv, PL_osname);
@@ -908,9 +933,12 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
        if (nextchar == '\0') {       /* ^P */
            sv_setiv(sv, (IV)PL_perldb);
        } else if (strEQ(remaining, "REMATCH")) { /* $^PREMATCH */
-           goto do_prematch_fetch;
+
+            paren = RX_BUFF_IDX_CARET_PREMATCH;
+           goto do_numbuf_fetch;
        } else if (strEQ(remaining, "OSTMATCH")) { /* $^POSTMATCH */
-           goto do_postmatch_fetch;
+            paren = RX_BUFF_IDX_CARET_POSTMATCH;
+           goto do_numbuf_fetch;
        }
        break;
     case '\023':               /* ^S */
@@ -973,55 +1001,46 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
        break;
     case '\015': /* $^MATCH */
        if (strEQ(remaining, "ATCH")) {
+            paren = RX_BUFF_IDX_CARET_FULLMATCH;
+           goto do_numbuf_fetch;
+        }
+
     case '1': case '2': case '3': case '4':
     case '5': case '6': case '7': case '8': case '9': case '&':
-           if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
-               /*
-                * Pre-threads, this was paren = atoi(GvENAME((const GV *)mg->mg_obj));
-                * XXX Does the new way break anything?
-                */
-               paren = atoi(mg->mg_ptr); /* $& is in [0] */
-               CALLREG_NUMBUF_FETCH(rx,paren,sv);
-               break;
-           }
-           sv_setsv(sv,&PL_sv_undef);
-       }
+        /*
+         * Pre-threads, this was paren = atoi(GvENAME((const GV *)mg->mg_obj));
+         * XXX Does the new way break anything?
+         */
+        paren = atoi(mg->mg_ptr); /* $& is in [0] */
+      do_numbuf_fetch:
+        if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
+            CALLREG_NUMBUF_FETCH(rx,paren,sv);
+            break;
+        }
+        sv_setsv(sv,&PL_sv_undef);
        break;
     case '+':
        if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
-           if (RX_LASTPAREN(rx)) {
-               CALLREG_NUMBUF_FETCH(rx,RX_LASTPAREN(rx),sv);
-               break;
-           }
+           paren = RX_LASTPAREN(rx);
+           if (paren)
+                goto do_numbuf_fetch;
        }
        sv_setsv(sv,&PL_sv_undef);
        break;
     case '\016':               /* ^N */
        if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
-           if (RX_LASTCLOSEPAREN(rx)) {
-               CALLREG_NUMBUF_FETCH(rx,RX_LASTCLOSEPAREN(rx),sv);
-               break;
-           }
-
+           paren = RX_LASTCLOSEPAREN(rx);
+           if (paren)
+                goto do_numbuf_fetch;
        }
        sv_setsv(sv,&PL_sv_undef);
        break;
     case '`':
-      do_prematch_fetch:
-       if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
-           CALLREG_NUMBUF_FETCH(rx,-2,sv);
-           break;
-       }
-       sv_setsv(sv,&PL_sv_undef);
-       break;
+        paren = RX_BUFF_IDX_PREMATCH;
+        goto do_numbuf_fetch;
     case '\'':
-      do_postmatch_fetch:
-       if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
-           CALLREG_NUMBUF_FETCH(rx,-1,sv);
-           break;
-       }
-       sv_setsv(sv,&PL_sv_undef);
-       break;
+        paren = RX_BUFF_IDX_POSTMATCH;
+        goto do_numbuf_fetch;
     case '.':
        if (GvIO(PL_last_in_gv)) {
            sv_setiv(sv, (IV)IoLINES(GvIOp(PL_last_in_gv)));
@@ -1513,7 +1532,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
     sigset_t set, save;
     SV* save_sv;
 #endif
-    register const char *s = MgPV_const(mg,len);
+    const char *s = MgPV_const(mg,len);
 
     PERL_ARGS_ASSERT_MAGIC_SETSIG;
 
@@ -2015,11 +2034,17 @@ Perl_magic_setdbline(pTHX_ SV *sv, MAGIC *mg)
     if (svp && SvIOKp(*svp)) {
        OP * const o = INT2PTR(OP*,SvIVX(*svp));
        if (o) {
+#ifdef PERL_DEBUG_READONLY_OPS
+           Slab_to_rw(OpSLAB(o));
+#endif
            /* set or clear breakpoint in the relevant control op */
            if (i)
                o->op_flags |= OPf_SPECIAL;
            else
                o->op_flags &= ~OPf_SPECIAL;
+#ifdef PERL_DEBUG_READONLY_OPS
+           Slab_to_ro(OpSLAB(o));
+#endif
        }
     }
     return 0;
@@ -2161,7 +2186,7 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg)
     pos = SvIV(sv);
 
     if (DO_UTF8(lsv)) {
-       ulen = sv_len_utf8(lsv);
+       ulen = sv_len_utf8_nomg(lsv);
        if (ulen)
            len = ulen;
     }
@@ -2175,9 +2200,7 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg)
        pos = len;
 
     if (ulen) {
-       I32 p = pos;
-       sv_pos_u2b(lsv, &p, 0);
-       pos = p;
+       pos = sv_pos_u2b_flags(lsv, pos, 0, 0);
     }
 
     found->mg_len = pos;
@@ -2201,7 +2224,7 @@ Perl_magic_getsubstr(pTHX_ SV *sv, MAGIC *mg)
     PERL_UNUSED_ARG(mg);
 
     if (!translate_substr_offsets(
-           SvUTF8(lsv) ? sv_len_utf8(lsv) : len,
+           SvUTF8(lsv) ? sv_len_utf8_nomg(lsv) : len,
            negoff ? -(IV)offs : (IV)offs, !negoff,
            negrem ? -(IV)rem  : (IV)rem,  !negrem, &offs, &rem
     )) {
@@ -2238,7 +2261,7 @@ Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg)
        Perl_ck_warner(aTHX_ packWARN(WARN_SUBSTR),
                            "Attempt to use reference as lvalue in substr"
        );
-    if (SvUTF8(lsv)) lsv_len = sv_len_utf8(lsv);
+    if (SvUTF8(lsv)) lsv_len = sv_len_utf8_nomg(lsv);
     else (void)SvPV_nomg(lsv,lsv_len);
     if (!translate_substr_offsets(
            lsv_len,
@@ -2326,19 +2349,6 @@ Perl_magic_setvec(pTHX_ SV *sv, MAGIC *mg)
 }
 
 int
-Perl_magic_setvstring(pTHX_ SV *sv, MAGIC *mg)
-{
-    PERL_ARGS_ASSERT_MAGIC_SETVSTRING;
-
-    if (SvPOKp(sv)) {
-       SV * const vecsv = sv_newmortal();
-       scan_vstring(mg->mg_ptr, mg->mg_ptr + mg->mg_len, vecsv);
-       if (sv_eq_flags(vecsv, sv, 0 /*nomg*/)) return 0;
-    }
-    return sv_unmagic(sv, mg->mg_type);
-}
-
-int
 Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg)
 {
     dVAR;
@@ -2511,9 +2521,9 @@ int
 Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
 {
     dVAR;
-    register const char *s;
-    register I32 paren;
-    register const REGEXP * rx;
+    const char *s;
+    I32 paren;
+    const REGEXP * rx;
     const char * const remaining = mg->mg_ptr + 1;
     I32 i;
     STRLEN len;
@@ -2555,7 +2565,8 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
         }
         break;
     case '\001':       /* ^A */
-       sv_setsv(PL_bodytarget, sv);
+       if (SvOK(sv)) sv_copypv(PL_bodytarget, sv);
+       else SvOK_off(PL_bodytarget);
        FmLINES(PL_bodytarget) = 0;
        if (SvPOK(PL_bodytarget)) {
            char *s = SvPVX(PL_bodytarget);
@@ -3087,7 +3098,7 @@ Perl_whichsig_pv(pTHX_ const char *sig)
 I32
 Perl_whichsig_pvn(pTHX_ const char *sig, STRLEN len)
 {
-    register char* const* sigv;
+    char* const* sigv;
 
     PERL_ARGS_ASSERT_WHICHSIG_PVN;
     PERL_UNUSED_CONTEXT;