Don’t LEAVE_with_name("evalcomp") for syntax errors
authorFather Chrysostomos <sprout@cpan.org>
Tue, 6 Dec 2011 16:34:15 +0000 (08:34 -0800)
committerFather Chrysostomos <sprout@cpan.org>
Tue, 6 Dec 2011 16:34:15 +0000 (08:34 -0800)
In S_doeval, if yystatus == 0 but there have been parser errors, then
there will be an extra scope on the scope stack inside the evalcomp
scope, causing an assertion failure with LEAVE_with_name("evalcomp").

This can happen with eval(q|""!=!~//|), which is a reduced version of
an eval in SNMP::Trapinfo’s test suite.

Under non-debugging builds, everything would have worked anyway,
as the LEAVE_with_name("evalcomp") would have left the scope
inside evalcomp.

Since POPBLOCK pops away the savestack markers on the scope stack, it
is not actually necessary to do LEAVE_with_name("evalcomp") at all
when there is a syntax error.

pp_ctl.c
t/op/eval.t

index 8e91ebd..b38e8e6 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -3588,8 +3588,6 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq, HV *hh)
 
     yystatus = (!in_require && CATCH_GET) ? S_try_yyparse(aTHX_ GRAMPROG) : yyparse(GRAMPROG);
 
-    if (!startop && yystatus != 3) LEAVE_with_name("evalcomp");
-
     if (yystatus || PL_parser->error_count || !PL_eval_root) {
        SV **newsp;                     /* Used by POPBLOCK. */
        PERL_CONTEXT *cx;
@@ -3615,6 +3613,7 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq, HV *hh)
                POPEVAL(cx);
                namesv = cx->blk_eval.old_namesv;
            }
+           /* POPBLOCK renders LEAVE_with_name("evalcomp") unnecessary. */
            LEAVE_with_name("eval"); /* pp_entereval knows about this LEAVE.  */
        }
 
@@ -3654,6 +3653,7 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq, HV *hh)
        PUTBACK;
        return FALSE;
     }
+    else if (!startop) LEAVE_with_name("evalcomp");
     CopLINE_set(&PL_compiling, 0);
     if (startop) {
        *startop = PL_eval_root;
index f8e23e3..78faa85 100644 (file)
@@ -6,7 +6,7 @@ BEGIN {
     require './test.pl';
 }
 
-plan(tests => 120);
+plan(tests => 121);
 
 eval 'pass();';
 
@@ -586,3 +586,8 @@ EOP
     BEGIN { eval 'require re; import re "/x"' }
     ok "ab" =~ /a b/, 'eval does not localise %^H at run time';
 }
+
+# The fix for perl #70151 caused an assertion failure that broke
+# SNMP::Trapinfo, when toke.c finds no syntax errors but perly.y fails.
+eval(q|""!=!~//|);
+pass("phew! dodged the assertion after a parsing (not lexing) error");