Stop (caller $n)[6] from including final "\n;"
authorFather Chrysostomos <sprout@cpan.org>
Tue, 28 Aug 2012 05:38:57 +0000 (22:38 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Tue, 28 Aug 2012 06:24:03 +0000 (23:24 -0700)
String eval appends "\n;" to the string before evaluating it.
(caller $n)[6], which returns the text of the eval, was giving the
modified string, rather than the original.

In fact, it was returning the actual string buffer that the parser
uses.  This commit changes it to create a new mortal SV from that
string buffer, but without the last two characters.

It unfortunately breaks this JAPH:

eval'BEGIN{${\(caller 2)[6]}=~y< !"$()+\-145=ACHMT^acfhinrsty{}>
<nlrhta"o Pe e,\nkrcrJ uthspeia">}say if+chr(1) -int"145"!=${^MATCH}'

pp_ctl.c
t/op/caller.t

index b4fd4dd..b85728b 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1857,7 +1857,9 @@ PP(pp_caller)
     if (CxTYPE(cx) == CXt_EVAL) {
        /* eval STRING */
        if (CxOLD_OP_TYPE(cx) == OP_ENTEREVAL) {
-           PUSHs(cx->blk_eval.cur_text);
+           PUSHs(newSVpvn_flags(SvPVX(cx->blk_eval.cur_text),
+                                SvCUR(cx->blk_eval.cur_text)-2,
+                                SvUTF8(cx->blk_eval.cur_text)|SVs_TEMP));
            PUSHs(&PL_sv_no);
        }
        /* require */
index 09d33f3..8c8c236 100644 (file)
@@ -5,7 +5,7 @@ BEGIN {
     chdir 't' if -d 't';
     @INC = '../lib';
     require './test.pl';
-    plan( tests => 86 );
+    plan( tests => 88 );
 }
 
 my @c;
@@ -266,6 +266,13 @@ foo::bar
 END
     "No crash when freed stash is reused for PV with offset hack";
 
+is eval "(caller 0)[6]", "(caller 0)[6]",
+  'eval text returned by caller does not include \n;';
+
+# PL_linestr should not be modifiable
+eval '"${;BEGIN{  ${\(caller 2)[6]} = *foo  }}"';
+pass "no assertion failure after modifying eval text via caller";
+
 $::testing_caller = 1;
 
 do './op/caller.pl' or die $@;