This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
avoid adding two OP_HINTSEVAL ops
authorDavid Mitchell <davem@iabyn.com>
Tue, 1 Jul 2014 14:42:42 +0000 (15:42 +0100)
committerDavid Mitchell <davem@iabyn.com>
Tue, 8 Jul 2014 15:40:03 +0000 (16:40 +0100)
Under argless eval (i.e. defaults to $_) in the presence of hints,
the perl core was recursively calling ck_eval, which had the side-effect
of attempting to append an OP_HINTSEVAL op twice. Formerly due to the way
the appending was done, the first OP_HINTSEVAL op was silently discarded;
after doing things "properly" with op_sibling_splice(), both ops ended up
being appended, and at run-time, the hints hash would be interpreted as
the SV to eval.

This wasn't tested in the core tests, and just ended up sometimes failing
warnings.t or Digest-SHA tests (but never on my system!)

op.c
t/op/eval.t

diff --git a/op.c b/op.c
index 8fbf2f8..e9de3a2 100644 (file)
--- a/op.c
+++ b/op.c
@@ -8727,7 +8727,11 @@ Perl_ck_eval(pTHX_ OP *o)
     else {
        const U8 priv = o->op_private;
        op_free(o);
-       o = newUNOP(OP_ENTEREVAL, priv <<8, newDEFSVOP());
+        /* the newUNOP will recursively call ck_eval(), which will handle
+         * all the stuff at the end of this function, like adding
+         * OP_HINTSEVAL
+         */
+       return newUNOP(OP_ENTEREVAL, priv <<8, newDEFSVOP());
     }
     o->op_targ = (PADOFFSET)PL_hints;
     if (o->op_private & OPpEVAL_BYTES) o->op_targ &= ~HINT_UTF8;
index e4c2f70..f404df5 100644 (file)
@@ -6,7 +6,7 @@ BEGIN {
     require './test.pl';
 }
 
-plan(tests => 130);
+plan(tests => 132);
 
 eval 'pass();';
 
@@ -517,6 +517,16 @@ END_EVAL_TEST
     is(Internals::SvREFCNT(%$t), $count_expected, 'RT 63110');
 }
 
+# make sure default arg eval only adds a hints hash once to entereval
+#
+{
+    local $_ = "21+12";
+    is(eval, 33, 'argless eval without hints');
+    use feature qw(:5.10);
+    local $_ = "42+24";
+    is(eval, 66, 'argless eval with hints');
+}
+
 {
     # test that the CV compiled for the eval is freed by checking that no additional 
     # reference to outside lexicals are made.