Note that sv_2mortal isn't just "increase reference count by 1, and
[p5sagit/p5-mst-13.2.git] / pp.c
diff --git a/pp.c b/pp.c
index 6a17ece..001b9be 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -168,6 +168,12 @@ PP(pp_rv2gv)
                    }
                    if (SvTYPE(sv) < SVt_RV)
                        sv_upgrade(sv, SVt_RV);
+                   if (SvPVX(sv)) {
+                       (void)SvOOK_off(sv);            /* backoff */
+                       if (SvLEN(sv))
+                           Safefree(SvPVX(sv));
+                       SvLEN(sv)=SvCUR(sv)=0;
+                   }
                    SvRV(sv) = (SV*)gv;
                    SvROK_on(sv);
                    SvSETMAGIC(sv);
@@ -1385,19 +1391,46 @@ PP(pp_repeat)
 {
   dSP; dATARGET; tryAMAGICbin(repeat,opASSIGN);
   {
-    register IV count = POPi;
-    if (count < 0)
-       count = 0;
+    register IV count;
+    dPOPss;
+    if (SvGMAGICAL(sv))
+        mg_get(sv);
+    if (SvIOKp(sv)) {
+        if (SvUOK(sv)) {
+             UV uv = SvUV(sv);
+             if (uv > IV_MAX)
+                  count = IV_MAX; /* The best we can do? */
+             else
+                  count = uv;
+        } else {
+             IV iv = SvIV(sv);
+             if (iv < 0)
+                  count = 0;
+             else
+                  count = iv;
+        }
+    }
+    else if (SvNOKp(sv)) {
+        NV nv = SvNV(sv);
+        if (nv < 0.0)
+             count = 0;
+        else
+             count = (IV)nv;
+    }
+    else
+        count = SvIVx(sv);
     if (GIMME == G_ARRAY && PL_op->op_private & OPpREPEAT_DOLIST) {
        dMARK;
        I32 items = SP - MARK;
        I32 max;
-       static const char list_extend[] = "panic: list extend";
+       static const char oom_list_extend[] =
+         "Out of memory during list extend";
 
        max = items * count;
-       MEM_WRAP_CHECK_1(max, SV*, list_extend);
+       MEM_WRAP_CHECK_1(max, SV*, oom_list_extend);
+       /* Did the max computation overflow? */
        if (items > 0 && max > 0 && (max < items || max < count))
-          Perl_croak(aTHX_ list_extend);
+          Perl_croak(aTHX_ oom_list_extend);
        MEXTEND(MARK, max);
        if (count > 1) {
            while (SP > MARK) {
@@ -1442,6 +1475,8 @@ PP(pp_repeat)
        SV *tmpstr = POPs;
        STRLEN len;
        bool isutf;
+       static const char oom_string_extend[] =
+         "Out of memory during string extend";
 
        SvSetSV(TARG, tmpstr);
        SvPV_force(TARG, len);
@@ -1450,7 +1485,10 @@ PP(pp_repeat)
            if (count < 1)
                SvCUR_set(TARG, 0);
            else {
-               MEM_WRAP_CHECK_1(count, len, "panic: string extend");
+               IV max = count * len;
+               if (len > ((MEM_SIZE)~0)/count)
+                    Perl_croak(aTHX_ oom_string_extend);
+               MEM_WRAP_CHECK_1(max, char, oom_string_extend);
                SvGROW(TARG, (count * len) + 1);
                repeatcpy(SvPVX(TARG) + len, SvPVX(TARG), len, count - 1);
                SvCUR(TARG) *= count;
@@ -2794,7 +2832,9 @@ PP(pp_int)
         else preferring IV has introduced a subtle behaviour change bug. OTOH
         relying on floating point to be accurate is a bug.  */
 
-      if (SvIOK(TOPs)) {
+      if (!SvOK(TOPs))
+        SETu(0);
+      else if (SvIOK(TOPs)) {
        if (SvIsUV(TOPs)) {
            UV uv = TOPu;
            SETu(uv);
@@ -2828,7 +2868,9 @@ PP(pp_abs)
       /* This will cache the NV value if string isn't actually integer  */
       IV iv = TOPi;
 
-      if (SvIOK(TOPs)) {
+      if (!SvOK(TOPs))
+        SETu(0);
+      else if (SvIOK(TOPs)) {
        /* IVX is precise  */
        if (SvIsUV(TOPs)) {
          SETu(TOPu);   /* force it to be numeric only */
@@ -3789,7 +3831,10 @@ PP(pp_delete)
            SP = ORIGMARK;
        else if (gimme == G_SCALAR) {
            MARK = ORIGMARK;
-           *++MARK = *SP;
+           if (SP > MARK)
+               *++MARK = *SP;
+           else
+               *++MARK = &PL_sv_undef;
            SP = MARK;
        }
     }
@@ -4321,12 +4366,17 @@ PP(pp_reverse)
        register I32 tmp;
        dTARGET;
        STRLEN len;
+       I32 padoff_du;
 
        SvUTF8_off(TARG);                               /* decontaminate */
        if (SP - MARK > 1)
            do_join(TARG, &PL_sv_no, MARK, SP);
        else
-           sv_setsv(TARG, (SP > MARK) ? *SP : DEFSV);
+           sv_setsv(TARG, (SP > MARK)
+                   ? *SP
+                   : (padoff_du = find_rundefsvoffset(),
+                       (padoff_du == NOT_IN_PAD || PAD_COMPNAME_FLAGS(padoff_du) & SVpad_OUR)
+                       ? DEFSV : PAD_SVl(padoff_du)));
        up = SvPV_force(TARG, len);
        if (len > 1) {
            if (DO_UTF8(TARG)) {        /* first reverse each character */
@@ -4630,7 +4680,7 @@ PP(pp_split)
            if (TOPs && !make_mortal)
                sv_2mortal(TOPs);
            iters--;
-           SP--;
+           *SP-- = &PL_sv_undef;
        }
     }