This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
don't lose mark when pp_reverse extends stack
authorZefram <zefram@fysh.org>
Fri, 8 Dec 2017 19:23:29 +0000 (19:23 +0000)
committerZefram <zefram@fysh.org>
Thu, 14 Dec 2017 19:38:52 +0000 (19:38 +0000)
Nullary reverse needs to extend the stack to push its result scalar.
It was actually extending the stack, but doing so invalidated MARK,
which it relied upon to place the stack pointer afterwards.  Upon stack
reallocation it was therefore leaving the stack pointer pointing to the
freed stack memory.  Reformulate stack manipulation to not rely on MARK
after extending.  Fixes [perl #132544].

pp.c
t/op/reverse.t

diff --git a/pp.c b/pp.c
index 3ef23ca..ae6d9c9 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -5613,13 +5613,16 @@ PP(pp_reverse)
        STRLEN len;
 
        SvUTF8_off(TARG);                               /* decontaminate */
-       if (SP - MARK > 1)
+       if (SP - MARK > 1) {
            do_join(TARG, &PL_sv_no, MARK, SP);
-       else if (SP > MARK)
+           SP = MARK + 1;
+           SETs(TARG);
+       } else if (SP > MARK) {
            sv_setsv(TARG, *SP);
-        else {
+           SETs(TARG);
+        } else {
            sv_setsv(TARG, DEFSV);
-            EXTEND(SP, 1);
+           XPUSHs(TARG);
        }
 
        up = SvPV_force(TARG, len);
@@ -5657,8 +5660,6 @@ PP(pp_reverse)
            }
            (void)SvPOK_only_UTF8(TARG);
        }
-       SP = MARK + 1;
-       SETTARG;
     }
     RETURN;
 }
index fd06560..a7d3178 100644 (file)
@@ -6,7 +6,7 @@ BEGIN {
     set_up_inc('../lib');
 }
 
-plan tests => 25;
+plan tests => 26;
 
 is(reverse("abc"), "cba", 'simple reverse');
 
@@ -105,3 +105,8 @@ SKIP: {
     ok defined $a[-1] && ${$a[-1]} eq '1', "in-place reverse strengthens weak reference";
     ok defined $a[2] && ${$a[2]} eq '3', "in-place reverse strengthens weak reference in the middle";
 }
+
+# [perl #132544] stack pointer used to go wild when nullary reverse
+# required extending the stack
+for(0..1000){()=(0..$_,scalar reverse )}
+pass "extending the stack without crashing";