Stop SEGV on 'our sub { syntax error }'
authorPeter Martini <PeterCMartini@GMail.com>
Sun, 3 Mar 2013 00:09:58 +0000 (00:09 +0000)
committerDavid Mitchell <davem@iabyn.com>
Sun, 3 Mar 2013 00:25:13 +0000 (00:25 +0000)
Fix for RT #116981. If a sub is declared with our, the name is added
to the stash early, and left with a NULL ptr if there's a syntax error
while compiling it.

Since the only time it becomes an issue is when that same name
is used in the same scope after a syntax error, what happens in
the pad is not particularly important.  The simple fix is to
simply fall back to treating it like a bareword, and pretending
it was never added to the pad in the first place.

t/cmd/lexsub.t
toke.c

index 86c7e26..46bab03 100644 (file)
@@ -8,7 +8,7 @@ BEGIN {
     *bar::like = *like;
 }
 no warnings 'deprecated';
-plan 128;
+BEGIN{plan 133;}
 
 # -------------------- Errors with feature disabled -------------------- #
 
@@ -95,6 +95,19 @@ sub bar::c { 43 }
   my $y = if if if;
   is $y, 42, 'our subs from other packages override all keywords';
 }
+# Make sure errors don't pollute the stash (see RT 116981)
+{
+  eval "our sub ln99{!} ln99(1)";
+  eval "ln99(1)";
+  like $@, "Undefined subroutine &main::ln99 called", "Bad definitions do not pollute the stash";
+  isnt $::{ln99}, -1, "No placeholder was entered";
+  our sub ln103;
+  is $::{ln103}, -1, "Placeholder was entered";
+  eval "our sub ln103{!} ln103(1)";
+  eval "ln103(1)";
+  like $@, "Undefined subroutine &main::ln103 called", "Bad definitions do not pollute the stash";
+  isnt $::{ln103}, -1, "Placeholder was removed";
+}
 
 # -------------------- state -------------------- #
 
diff --git a/toke.c b/toke.c
index aace60b..006f885 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -6900,6 +6900,11 @@ Perl_yylex(pTHX)
                    gv = gv_fetchsv(sv, GV_NOADD_NOINIT | SvUTF8(sv),
                                    SVt_PVCV);
                    off = 0;
+                   if (!gv) {
+                       sv_free(sv);
+                       sv = NULL;
+                       goto just_a_word;
+                   }
                }
                else {
                    rv2cv_op = newOP(OP_PADANY, 0);