This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Removed the ifdefs for INCOMPLETE_TAINTS
[perl5.git] / pp_ctl.c
index 2f2dd79..f258976 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -168,12 +168,10 @@ PP(pp_regcomp)
     }
 
 
-#ifndef INCOMPLETE_TAINTS
     if (TAINTING_get && TAINT_get) {
        SvTAINTED_on((SV*)new_re);
         RX_TAINT_on(new_re);
     }
-#endif
 
 #if !defined(USE_ITHREADS)
     /* can't change the optree at runtime either */
@@ -226,14 +224,10 @@ PP(pp_substcont)
        if (SvTAINTED(TOPs))
            cx->sb_rxtainted |= SUBST_TAINT_REPL;
        sv_catsv_nomg(dstr, POPs);
-       /* XXX: adjust for positive offsets of \G for instance s/(.)\G//g with positive pos() */
-       s -= RX_GOFS(rx);
-
-       /* Are we done */
        if (CxONCE(cx) || s < orig ||
-               !CALLREGEXEC(rx, s, cx->sb_strend, orig,
-                            (s == m) + RX_GOFS(rx), cx->sb_targ, NULL,
-                                (REXEC_IGNOREPOS|REXEC_NOT_FIRST)))
+                !CALLREGEXEC(rx, s, cx->sb_strend, orig,
+                            (s == m), cx->sb_targ, NULL,
+                    (REXEC_IGNOREPOS|REXEC_NOT_FIRST|REXEC_FAIL_ON_UNDERFLOW)))
        {
            SV *targ = cx->sb_targ;
 
@@ -254,12 +248,9 @@ PP(pp_substcont)
                targ = dstr;
            }
            else {
-               if (SvIsCOW(targ)) {
-                   sv_force_normal_flags(targ, SV_COW_DROP_PV);
-               } else
-               {
-                   SvPV_free(targ);
-               }
+               SV_CHECK_THINKFIRST_COW_DROP(targ);
+               if (isGV(targ)) Perl_croak_no_modify();
+               SvPV_free(targ);
                SvPV_set(targ, SvPVX(dstr));
                SvCUR_set(targ, SvCUR(dstr));
                SvLEN_set(targ, SvLEN(dstr));
@@ -325,16 +316,11 @@ PP(pp_substcont)
        SV * const sv
            = (pm->op_pmflags & PMf_NONDESTRUCT) ? cx->sb_dstr : cx->sb_targ;
        MAGIC *mg;
-       SvUPGRADE(sv, SVt_PVMG);
-       if (!(mg = mg_find(sv, PERL_MAGIC_regex_global))) {
-#ifdef PERL_OLD_COPY_ON_WRITE
-           if (SvIsCOW(sv))
-               sv_force_normal_flags(sv, 0);
-#endif
-           mg = sv_magicext(sv, NULL, PERL_MAGIC_regex_global, &PL_vtbl_mglob,
-                            NULL, 0);
+       if (!(mg = mg_find_mglob(sv))) {
+           mg = sv_magicext_mglob(sv);
        }
-       mg->mg_len = m - orig;
+       assert(SvPOK(dstr));
+       MgBYTEPOS_set(mg, sv, SvPVX(dstr), m - orig);
     }
     if (old != rx)
        (void)ReREFCNT_inc(rx);
@@ -599,7 +585,7 @@ PP(pp_formline)
                            itembytes = len;
                        send = chophere = s + itembytes;
                        while (s < send) {
-                           if (*s & ~31)
+                           if (! isCNTRL(*s))
                                gotsome = TRUE;
                            else if (*s == '\n')
                                break;
@@ -616,7 +602,7 @@ PP(pp_formline)
                    itemsize = fieldsize;
                send = chophere = s + itemsize;
                while (s < send) {
-                   if (*s & ~31)
+                   if (! isCNTRL(*s))
                        gotsome = TRUE;
                    else if (*s == '\n')
                        break;
@@ -642,8 +628,9 @@ PP(pp_formline)
                                    chophere = s;
                                    break;
                                }
-                               if (*s++ & ~31)
+                               if (! isCNTRL(*s))
                                    gotsome = TRUE;
+                                s++;
                            }
                        }
                        else {
@@ -660,7 +647,7 @@ PP(pp_formline)
                                        break;
                                }
                                else {
-                                   if (*s & ~31)
+                                   if (! isCNTRL(*s))
                                        gotsome = TRUE;
                                    if (strchr(PL_chopset, *s))
                                        chophere = s + 1;
@@ -683,8 +670,9 @@ PP(pp_formline)
                            chophere = s;
                            break;
                        }
-                       if (*s++ & ~31)
+                       if (! isCNTRL(*s))
                            gotsome = TRUE;
+                        s++;
                    }
                }
                else {
@@ -699,7 +687,7 @@ PP(pp_formline)
                                break;
                        }
                        else {
-                           if (*s & ~31)
+                           if (! isCNTRL(*s))
                                gotsome = TRUE;
                            if (strchr(PL_chopset, *s))
                                chophere = s + 1;
@@ -841,13 +829,7 @@ PP(pp_formline)
                    U8 *send = s + to_copy;
                    while (s < send) {
                        const int ch = *s;
-                       if (trans == '~' ? (ch == '~') :
-#ifdef EBCDIC
-                              iscntrl(ch)
-#else
-                              (!(ch & ~31))
-#endif
-                       )
+                       if (trans == '~' ? (ch == '~') : isCNTRL(ch))
                            *s = ' ';
                        s++;
                    }
@@ -999,6 +981,10 @@ PP(pp_grepstart)
     SAVEVPTR(PL_curpm);
 
     src = PL_stack_base[*PL_markstack_ptr];
+    if (SvPADTMP(src) && !IS_PADGV(src)) {
+       src = PL_stack_base[*PL_markstack_ptr] = sv_mortalcopy(src);
+       PL_tmps_floor++;
+    }
     SvTEMP_off(src);
     if (PL_op->op_private & OPpGREP_LEX)
        PAD_SVl(PL_op->op_targ) = src;
@@ -1147,6 +1133,7 @@ PP(pp_mapwhile)
 
        /* set $_ to the new source item */
        src = PL_stack_base[PL_markstack_ptr[-1]];
+       if (SvPADTMP(src) && !IS_PADGV(src)) src = sv_mortalcopy(src);
        SvTEMP_off(src);
        if (PL_op->op_private & OPpGREP_LEX)
            PAD_SVl(PL_op->op_targ) = src;
@@ -1238,13 +1225,17 @@ PP(pp_flop)
        if (RANGE_IS_NUMERIC(left,right)) {
            IV i, j;
            IV max;
-           if ((SvOK(left) && SvNV_nomg(left) < IV_MIN) ||
-               (SvOK(right) && SvNV_nomg(right) > IV_MAX))
+           if ((SvOK(left) && !SvIOK(left) && SvNV_nomg(left) < IV_MIN) ||
+               (SvOK(right) && (SvIOK(right)
+                                ? SvIsUV(right) && SvUV(right) > IV_MAX
+                                : SvNV_nomg(right) > IV_MAX)))
                DIE(aTHX_ "Range iterator outside integer range");
            i = SvIV_nomg(left);
            max = SvIV_nomg(right);
            if (max >= i) {
                j = max - i + 1;
+               if (j > SSize_t_MAX)
+                   Perl_croak(aTHX_ "Out of memory during list extend");
                EXTEND_MORTAL(j);
                EXTEND(SP, j);
            }
@@ -1818,6 +1809,7 @@ PP(pp_caller)
     const HEK *stash_hek;
     I32 count = 0;
     bool has_arg = MAXARG && TOPs;
+    const COP *lcop;
 
     if (MAXARG) {
       if (has_arg)
@@ -1861,7 +1853,11 @@ PP(pp_caller)
        PUSHTARG;
     }
     mPUSHs(newSVpv(OutCopFILE(cx->blk_oldcop), 0));
-    mPUSHi((I32)CopLINE(cx->blk_oldcop));
+    lcop = closest_cop(cx->blk_oldcop, cx->blk_oldcop->op_sibling,
+                      cx->blk_sub.retop, TRUE);
+    if (!lcop)
+       lcop = cx->blk_oldcop;
+    mPUSHi((I32)CopLINE(lcop));
     if (!has_arg)
        RETURN;
     if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) {
@@ -1914,7 +1910,7 @@ PP(pp_caller)
        && CopSTASH_eq(PL_curcop, PL_debstash))
     {
        AV * const ary = cx->blk_sub.argarray;
-       const int off = AvARRAY(ary) - AvALLOC(ary);
+       const SSize_t off = AvARRAY(ary) - AvALLOC(ary);
 
        Perl_init_dbargs(aTHX);
 
@@ -2463,8 +2459,8 @@ PP(pp_return)
        }
        break;
     case CXt_FORMAT:
-       POPFORMAT(cx);
        retop = cx->blk_sub.retop;
+       POPFORMAT(cx);
        break;
     default:
        DIE(aTHX_ "panic: return, type=%u", (unsigned) CxTYPE(cx));
@@ -2553,8 +2549,8 @@ PP(pp_leavesublv)
     S_return_lvalues(aTHX_ newsp, SP, newsp, gimme, cx, newpm);
 
     LEAVE;
-    cxstack_ix--;
     POPSUB(cx,sv);     /* Stack values are safe: release CV and @_ ... */
+    cxstack_ix--;
     PL_curpm = newpm;  /* ... and pop $1 et al */
 
     LEAVESUB(sv);
@@ -2618,7 +2614,6 @@ PP(pp_last)
 
     POPBLOCK(cx,newpm);
     cxstack_ix++; /* temporarily protect top context */
-    mark = newsp;
     switch (CxTYPE(cx)) {
     case CXt_LOOP_LAZYIV:
     case CXt_LOOP_LAZYSV:
@@ -2645,8 +2640,7 @@ PP(pp_last)
     }
 
     TAINT_NOT;
-    PL_stack_sp = adjust_stack_on_leave(newsp, PL_stack_sp, MARK, gimme,
-                               pop2 == CXt_SUB ? SVs_TEMP : 0);
+    PL_stack_sp = newsp;
 
     LEAVE;
     cxstack_ix--;
@@ -2778,7 +2772,7 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac
     return 0;
 }
 
-PP(pp_goto)
+PP(pp_goto) /* also pp_dump */
 {
     dVAR; dSP;
     OP *retop = NULL;
@@ -2793,6 +2787,8 @@ PP(pp_goto)
     static const char* const must_have_label = "goto must have label";
 
     if (PL_op->op_flags & OPf_STACKED) {
+        /* goto EXPR  or  goto &foo */
+
        SV * const sv = POPs;
        SvGETMAGIC(sv);
 
@@ -2895,22 +2891,35 @@ PP(pp_goto)
                OP* const retop = cx->blk_sub.retop;
                SV **newsp;
                I32 gimme;
-               const SSize_t items = AvFILLp(arg) + 1;
+               const SSize_t items = arg ? AvFILL(arg) + 1 : 0;
+               const bool m = arg ? cBOOL(SvRMAGICAL(arg)) : 0;
                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*);
+               if (items) {
+                   EXTEND(SP, items+1); /* @_ could have been extended. */
+               }
                mark = SP;
-               SP += items;
-               if (AvREAL(arg)) {
-                   I32 index;
+               if (items) {
+                   SSize_t index;
+                   bool r = cBOOL(AvREAL(arg));
                    for (index=0; index<items; index++)
-                       SvREFCNT_inc_void(sv_2mortal(SP[-index]));
+                   {
+                       SV *sv;
+                       if (m) {
+                           SV ** const svp = av_fetch(arg, index, 0);
+                           sv = svp ? *svp : NULL;
+                       }
+                       else sv = AvARRAY(arg)[index];
+                       SP[index+1] = sv
+                           ? r ? SvREFCNT_inc_NN(sv_2mortal(sv)) : sv
+                           : sv_2mortal(newSVavdefelem(arg, index, 1));
+                   }
                }
+               SP += items;
                SvREFCNT_dec(arg);
                if (CxTYPE(cx) == CXt_SUB && CxHASARGS(cx)) {
                    /* Restore old @_ */
@@ -2983,11 +2992,13 @@ PP(pp_goto)
            }
        }
        else {
+            /* goto EXPR */
            label       = SvPV_nomg_const(sv, label_len);
             label_flags = SvUTF8(sv);
        }
     }
     else if (!(PL_op->op_flags & OPf_SPECIAL)) {
+        /* goto LABEL  or  dump LABEL */
        label       = cPVOP->op_pv;
         label_flags = (cPVOP->op_private & OPpPV_IS_UTF8) ? SVf_UTF8 : 0;
         label_len   = strlen(label);
@@ -3071,7 +3082,7 @@ PP(pp_goto)
        }
        if (!retop)
            DIE(aTHX_ "Can't find label %"UTF8f, 
-                            label_flags, label_len, label);
+                      UTF8fARG(label_flags, label_len, label));
 
        /* if we're leaving an eval, check before we pop any frames
            that we're not going to punt, otherwise the error
@@ -3279,7 +3290,11 @@ Perl_find_runcv_where(pTHX_ U8 cond, IV arg, U32 *db_seqp)
     int                 level = 0;
 
     if (db_seqp)
-       *db_seqp = PL_curcop->cop_seq;
+       *db_seqp =
+            PL_curcop == &PL_compiling
+                ? PL_cop_seqmax
+                : PL_curcop->cop_seq;
+
     for (si = PL_curstackinfo; si; si = si->si_prev) {
         I32 ix;
        for (ix = si->si_cxix; ix >= 0; ix--) {
@@ -3584,11 +3599,23 @@ STATIC PerlIO *
 S_check_type_and_open(pTHX_ SV *name)
 {
     Stat_t st;
-    const char *p = SvPV_nolen_const(name);
-    const int st_rc = PerlLIO_stat(p, &st);
+    STRLEN len;
+    const char *p = SvPV_const(name, len);
+    int st_rc;
 
     PERL_ARGS_ASSERT_CHECK_TYPE_AND_OPEN;
 
+    /* checking here captures a reasonable error message when
+     * PERL_DISABLE_PMC is true, but when PMC checks are enabled, the
+     * user gets a confusing message about looking for the .pmc file
+     * rather than for the .pm file.
+     * This check prevents a \0 in @INC causing problems.
+     */
+    if (!IS_SAFE_PATHNAME(p, len, "require"))
+        return NULL;
+
+    st_rc = PerlLIO_stat(p, &st);
+
     if (st_rc < 0 || S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode)) {
        return NULL;
     }
@@ -3609,6 +3636,13 @@ S_doopen_pm(pTHX_ SV *name)
 
     PERL_ARGS_ASSERT_DOOPEN_PM;
 
+    /* check the name before trying for the .pmc name to avoid the
+     * warning referring to the .pmc which the user probably doesn't
+     * know or care about
+     */
+    if (!IS_SAFE_PATHNAME(p, namelen, "require"))
+        return NULL;
+
     if (namelen > 3 && memEQs(p + namelen - 3, 3, ".pm")) {
        SV *const pmcsv = sv_newmortal();
        Stat_t pmcstat;
@@ -3741,6 +3775,12 @@ PP(pp_require)
     name = SvPV_const(sv, len);
     if (!(name && len > 0 && *name))
        DIE(aTHX_ "Null filename used");
+    if (!IS_SAFE_PATHNAME(name, len, "require")) {
+        DIE(aTHX_ "Can't locate %s:   %s",
+            pv_escape(newSVpvs_flags("",SVs_TEMP),SvPVX(sv),SvCUR(sv),
+                      SvCUR(sv)*2,NULL, SvUTF8(sv)?PERL_PV_ESCAPE_UNI:0),
+            Strerror(ENOENT));
+    }
     TAINT_PROPER("require");
 
     path_searchable = path_is_searchable(name);
@@ -3790,7 +3830,7 @@ PP(pp_require)
     }
     if (!tryrsfp && !(errno == EACCES && !path_searchable)) {
        AV * const ar = GvAVn(PL_incgv);
-       I32 i;
+       SSize_t i;
 #ifdef VMS
        if (vms_unixname)
 #endif
@@ -3887,10 +3927,16 @@ PP(pp_require)
                        SP--;
                    }
 
+                   /* FREETMPS may free our filter_cache */
+                   SvREFCNT_inc_simple_void(filter_cache);
+
                    PUTBACK;
                    FREETMPS;
                    LEAVE_with_name("call_INC");
 
+                   /* Now re-mortalize it. */
+                   sv_2mortal(filter_cache);
+
                    /* Adjust file name if the hook has set an %INC entry.
                       This needs to happen after the FREETMPS above.  */
                    svp = hv_fetch(GvHVn(PL_incgv), name, len, 0);
@@ -3925,6 +3971,8 @@ PP(pp_require)
                        dirlen = 0;
                    }
 
+                   if (!IS_SAFE_SYSCALL(dir, dirlen, "@INC entry", "require"))
+                       continue;
 #ifdef VMS
                    if (((unixdirbuf = SvPVX(sv_2mortal(newSVpv("", VMS_MAXRSS-1)))) == NULL)
                        || ((unixdir = tounixpath(dir, unixdirbuf)) == NULL))
@@ -4003,7 +4051,7 @@ PP(pp_require)
            } else {
                if (namesv) {                   /* did we lookup @INC? */
                    AV * const ar = GvAVn(PL_incgv);
-                   I32 i;
+                   SSize_t i;
                    SV *const msg = newSVpvs_flags("", SVs_TEMP);
                    SV *const inc = newSVpvs_flags("", SVs_TEMP);
                    for (i = 0; i <= AvFILL(ar); i++) {
@@ -4570,7 +4618,7 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied)
        }
        else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVAV) {
            /* Test sub truth for each element */
-           I32 i;
+           SSize_t i;
            bool andedresults = TRUE;
            AV *av = (AV*) SvRV(d);
            const I32 len = av_len(av);
@@ -4685,8 +4733,8 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied)
        }
        else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVAV) {
            AV * const other_av = MUTABLE_AV(SvRV(d));
-           const I32 other_len = av_len(other_av) + 1;
-           I32 i;
+           const SSize_t other_len = av_len(other_av) + 1;
+           SSize_t i;
            HV *hv = MUTABLE_HV(SvRV(e));
 
            DEBUG_M(Perl_deb(aTHX_ "    applying rule Array-Hash\n"));
@@ -4737,8 +4785,8 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied)
        }
        else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVHV) {
            AV * const other_av = MUTABLE_AV(SvRV(e));
-           const I32 other_len = av_len(other_av) + 1;
-           I32 i;
+           const SSize_t other_len = av_len(other_av) + 1;
+           SSize_t i;
 
            DEBUG_M(Perl_deb(aTHX_ "    applying rule Hash-Array\n"));
            for (i = 0; i < other_len; ++i) {
@@ -4758,8 +4806,8 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied)
            if (av_len(MUTABLE_AV(SvRV(e))) != av_len(other_av))
                RETPUSHNO;
            else {
-               I32 i;
-               const I32 other_len = av_len(other_av);
+               SSize_t i;
+               const SSize_t other_len = av_len(other_av);
 
                if (NULL == seen_this) {
                    seen_this = newHV();
@@ -4814,8 +4862,8 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied)
          sm_regex_array:
            {
                PMOP * const matcher = make_matcher((REGEXP*) SvRV(d));
-               const I32 this_len = av_len(MUTABLE_AV(SvRV(e)));
-               I32 i;
+               const SSize_t this_len = av_len(MUTABLE_AV(SvRV(e)));
+               SSize_t i;
 
                for(i = 0; i <= this_len; ++i) {
                    SV * const * const svp = av_fetch(MUTABLE_AV(SvRV(e)), i, FALSE);
@@ -4831,8 +4879,8 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied)
        }
        else if (!SvOK(d)) {
            /* undef ~~ array */
-           const I32 this_len = av_len(MUTABLE_AV(SvRV(e)));
-           I32 i;
+           const SSize_t this_len = av_len(MUTABLE_AV(SvRV(e)));
+           SSize_t i;
 
            DEBUG_M(Perl_deb(aTHX_ "    applying rule Undef-Array\n"));
            for (i = 0; i <= this_len; ++i) {
@@ -4846,8 +4894,8 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied)
        else {
          sm_any_array:
            {
-               I32 i;
-               const I32 this_len = av_len(MUTABLE_AV(SvRV(e)));
+               SSize_t i;
+               const SSize_t this_len = av_len(MUTABLE_AV(SvRV(e)));
 
                DEBUG_M(Perl_deb(aTHX_ "    applying rule Any-Array\n"));
                for (i = 0; i <= this_len; ++i) {
@@ -5447,6 +5495,7 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
 
        if (count > 0) {
            SV *out = POPs;
+           SvGETMAGIC(out);
            if (SvOK(out)) {
                status = SvIV(out);
            }
@@ -5462,9 +5511,13 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
        LEAVE_with_name("call_filter_sub");
     }
 
+    if (SvGMAGICAL(upstream)) {
+       mg_get(upstream);
+       if (upstream == buf_sv) mg_free(buf_sv);
+    }
     if (SvIsCOW(upstream)) sv_force_normal(upstream);
     if(!err && SvOK(upstream)) {
-       got_p = SvPV(upstream, got_len);
+       got_p = SvPV_nomg(upstream, got_len);
        if (umaxlen) {
            if (got_len > umaxlen) {
                prune_from = got_p + umaxlen;
@@ -5495,7 +5548,12 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
        if (SvUTF8(upstream)) {
            SvUTF8_on(cache);
        }
-       SvCUR_set(upstream, got_len - cached_len);
+       if (SvPOK(upstream)) SvCUR_set(upstream, got_len - cached_len);
+       else
+           /* Cannot just use sv_setpvn, as that could free the buffer
+              before we have a chance to assign it. */
+           sv_usepvn(upstream, savepvn(got_p, got_len - cached_len),
+                     got_len - cached_len);
        *prune_from = 0;
        /* Can't yet be EOF  */
        if (status == 0)
@@ -5507,9 +5565,10 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
        concatenate it then we get a warning about use of uninitialised value.
     */
     if (!err && upstream != buf_sv &&
-        (SvOK(upstream) || SvGMAGICAL(upstream))) {
-       sv_catsv(buf_sv, upstream);
+        SvOK(upstream)) {
+       sv_catsv_nomg(buf_sv, upstream);
     }
+    else if (SvOK(upstream)) (void)SvPV_force_nolen(buf_sv);
 
     if (status <= 0) {
        IoLINES(datasv) = 0;