summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2015-08-20 09:03:17 +0100
committerSteve Hay <steve.m.hay@googlemail.com>2015-08-28 20:44:38 +0100
commitfeac78b0722d4899f9a306d5fb427fe33e82b9ab (patch)
tree779d92f5ad28645268a077ad4aa10515230a96e6
parent89d3bf64c47772a0c299cec5555c07c208dd1fbf (diff)
downloadperl-feac78b0722d4899f9a306d5fb427fe33e82b9ab.tar.gz
[perl #123712] Don’t check sub_inwhat
PL_sublex_info.sub_inwhat (in the parser struct) is a temporary spot to store the value of PL_lex_inwhat (also in the parser struct) when a sub-lexing scope (for a quote-like operator) is entered. PL_lex_inwhat is localised, and the value is copied from its temporary spot (sub_inwhat) into PL_lex_inwhat. The PL_sublex_info.sub_inwhat was not localised, but instead the value was set to 0 when a sub-lexing scope was exited. This value was being used, in a couple of places, to determine whether we were inside a quote-like operator. But because the value is not localised, it can be wrong when it is set to 0, if we have nested lexing scopes. So this ends up crashing for the same reason described in e47d32dcd5: echo -n '/$a[m||/<<a' | ./miniperl perl-5.005_02-1816-g09bef84 added the first use of PL_sublex_info.sub_inwhat to determine whether we are in a quote-like operator. (Later it got shifted around.) I copied that in e47d32dcd5 (earlier today), because I assumed the logic was correct. Other parts of the code use PL_lex_inwhat, which is already localised, as I said, and does not suffer this problem. If we do not check PL_sublex_info.sub_inwhat to see if we are in a quote-like construct, then we don’t need to clear it on lexing scope exit. (cherry picked from commit d27f4b916ce5819f564bdd4a135137c457156333)
-rw-r--r--t/op/lex.t9
-rw-r--r--toke.c5
2 files changed, 10 insertions, 4 deletions
diff --git a/t/op/lex.t b/t/op/lex.t
index 35d4d9c3de..ac094f8d5f 100644
--- a/t/op/lex.t
+++ b/t/op/lex.t
@@ -4,7 +4,7 @@ use warnings;
BEGIN { chdir 't'; require './test.pl'; }
-plan(tests => 9);
+plan(tests => 10);
{
no warnings 'deprecated';
@@ -96,3 +96,10 @@ fresh_perl_is(
{ stderr => 1 },
'/$a[/<<a with no newline [perl #123712]'
);
+fresh_perl_is(
+ '/$a[m||/<<a',
+ "syntax error at - line 1, next char ;\n" .
+ "Execution of - aborted due to compilation errors.\n",
+ { stderr => 1 },
+ '/$a[m||/<<a with no newline [perl #123712]'
+);
diff --git a/toke.c b/toke.c
index 90642b25e0..f59f913486 100644
--- a/toke.c
+++ b/toke.c
@@ -1315,7 +1315,7 @@ Perl_lex_next_chunk(pTHX_ U32 flags)
bool got_some;
if (flags & ~(LEX_KEEP_PREVIOUS|LEX_FAKE_EOF|LEX_NO_TERM))
Perl_croak(aTHX_ "Lexing code internal error (%s)", "lex_next_chunk");
- if (!(flags & LEX_NO_TERM) && PL_sublex_info.sub_inwhat)
+ if (!(flags & LEX_NO_TERM) && PL_lex_inwhat)
return FALSE;
linestr = PL_parser->linestr;
buf = SvPVX(linestr);
@@ -1962,7 +1962,7 @@ S_skipspace_flags(pTHX_ char *s, U32 flags)
STRLEN bufptr_pos = PL_bufptr - SvPVX(PL_linestr);
PL_bufptr = s;
lex_read_space(flags | LEX_KEEP_PREVIOUS |
- (PL_sublex_info.sub_inwhat || PL_lex_state == LEX_FORMLINE ?
+ (PL_lex_inwhat || PL_lex_state == LEX_FORMLINE ?
LEX_NO_NEXT_CHUNK : 0));
s = PL_bufptr;
PL_bufptr = SvPVX(PL_linestr) + bufptr_pos;
@@ -2797,7 +2797,6 @@ S_sublex_done(pTHX)
PL_bufend = SvPVX(PL_linestr);
PL_bufend += SvCUR(PL_linestr);
PL_expect = XOPERATOR;
- PL_sublex_info.sub_inwhat = 0;
return ')';
}
}