34484a
From 695d6585affc8f13711f013329fb4810ab89d833 Mon Sep 17 00:00:00 2001
34484a
From: Father Chrysostomos <sprout@cpan.org>
34484a
Date: Tue, 14 Nov 2017 18:55:55 -0800
34484a
Subject: [PATCH] [perl #132442] Fix stack with do {my sub l; 1}
34484a
MIME-Version: 1.0
34484a
Content-Type: text/plain; charset=UTF-8
34484a
Content-Transfer-Encoding: 8bit
34484a
34484a
A block in perl usually compiles to a leave op with an enter inside
34484a
it, followed by the statements:
34484a
34484a
   leave
34484a
     enter
34484a
     nextstate
34484a
     ... expr ...
34484a
     nextstate
34484a
     ... expr ...
34484a
34484a
If a block contains only one statement, and that statement is suffic-
34484a
iently innocuous, then the enter/leave pair to create the scope at run
34484a
time get skipped, and instead we have a simple scope op which is not
34484a
even executed:
34484a
34484a
   scope
34484a
     ex-nextstate
34484a
     ... expr ...
34484a
34484a
The nextstate in this case also gets nulled.
34484a
34484a
In the case of do { my sub l; 1 } we were getting a variation of the
34484a
latter, that looked like this:
34484a
34484a
   scope
34484a
     introcv
34484a
     clonecv
34484a
     nextstate
34484a
     ... expr ...
34484a
34484a
The problem here is that nextstate resets the stack, even though a new
34484a
scope has not been pushed, so we end up with all existing stack items
34484a
from the *outer* scope getting clobbered.
34484a
34484a
One can have fun with this and erase everything pushed on to the stack
34484a
so far in a given statement:
34484a
34484a
$ ./perl -le 'print join "-", 1..10, do {my sub l; ","}, 11..20'
34484a
11,12,13,14,15,16,17,18,19,20
34484a
34484a
Here I replaced the first argument to join() from within the do{}
34484a
block, after having cleared the stack.
34484a
34484a
Why was the op tree was getting muddled up like this?  The ‘my sub’
34484a
declaration does not immediately add any ops to the op tree; those ops
34484a
get added when the current scope finishing compiling, since those ops
34484a
must be inserted at the beginning of the block.
34484a
34484a
I have not fully looked into the order that things happen, and why the
34484a
nextstate op does not get nulled; but it did not matter, because of
34484a
the simple fix: Treat lexical sub declarations as ‘not innocuous’ by
34484a
setting the HINT_BLOCK_SCOPE flag when a lexical sub is declared.
34484a
Thus, we end up with an enter/leave pair, which creates a
34484a
proper scope.
34484a
34484a
Signed-off-by: Petr Písař <ppisar@redhat.com>
34484a
---
34484a
 op.c          | 2 ++
34484a
 t/op/lexsub.t | 5 ++++-
34484a
 2 files changed, 6 insertions(+), 1 deletion(-)
34484a
34484a
diff --git a/op.c b/op.c
34484a
index 8fa5aad876..c617ad2a00 100644
34484a
--- a/op.c
34484a
+++ b/op.c
34484a
@@ -9243,6 +9243,8 @@ Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
34484a
 
34484a
     PERL_ARGS_ASSERT_NEWMYSUB;
34484a
 
34484a
+    PL_hints |= HINT_BLOCK_SCOPE;
34484a
+
34484a
     /* Find the pad slot for storing the new sub.
34484a
        We cannot use PL_comppad, as it is the pad owned by the new sub.  We
34484a
        need to look in CvOUTSIDE and find the pad belonging to the enclos-
34484a
diff --git a/t/op/lexsub.t b/t/op/lexsub.t
34484a
index 3fa17acdda..f085cd97e8 100644
34484a
--- a/t/op/lexsub.t
34484a
+++ b/t/op/lexsub.t
34484a
@@ -7,7 +7,7 @@ BEGIN {
34484a
     *bar::is = *is;
34484a
     *bar::like = *like;
34484a
 }
34484a
-plan 149;
34484a
+plan 150;
34484a
 
34484a
 # -------------------- our -------------------- #
34484a
 
34484a
@@ -957,3 +957,6 @@ like runperl(
34484a
 {
34484a
   my sub h; sub{my $x; sub{h}}
34484a
 }
34484a
+
34484a
+is join("-", qw(aa bb), do { my sub lleexx; 123 }, qw(cc dd)),
34484a
+  "aa-bb-123-cc-dd", 'do { my sub...} in a list [perl #132442]';
34484a
-- 
34484a
2.13.6
34484a