summaryrefslogtreecommitdiff
path: root/toke.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2015-04-15 08:47:18 +0100
committerDavid Mitchell <davem@iabyn.com>2015-04-15 08:47:18 +0100
commitc7f317a9270a52c9028667b8adec18e94f450586 (patch)
tree836eab4f0534a79f8c51fa6aa8e9e0b8fee5b097 /toke.c
parent2c0445268a1bb7696e04b8b9b324c3d6880bb18a (diff)
downloadperl-c7f317a9270a52c9028667b8adec18e94f450586.tar.gz
assertion failure on interpolated parse err
RT# 124216 When paring the interpolated string "$X", where X is a unicode char that is not a legal variable name, failure to restore things properly during error recovery led to corrupted state and assertion failures. In more detail: When parsing a double-quoted string, S_sublex_push() saves most of the current parser state. On parse error, the save stack is popped back, which restores all that state. However, PL_lex_defer wasn't being saved, so if we were in the middle of handling a forced token, PL_lex_state gets restored from PL_lex_defer, and suddenly the lexer thinks we're back inside an interpolated string again. So S_sublex_done() gets called multiple times, too many scopes are popped, and things like PL_compcv are freed prematurely. Note that in order to reproduce: * we must be within a double quoted context; * we must be parsing a var (which causes a forced token); * the variable name must be illegal, which implies unicode, as chr(0..255) are all legal names; * the terminating string quote must be the last char of the input file, as this code: case LEX_INTERPSTART: if (PL_bufptr == PL_bufend) return REPORT(sublex_done()); won't trigger an extra call to sublex_done() otherwise. I'm sure this bug affects other cases too, but this was the only way I found to reproduce.
Diffstat (limited to 'toke.c')
-rw-r--r--toke.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/toke.c b/toke.c
index 2a99f0b4b3..294cb8fd54 100644
--- a/toke.c
+++ b/toke.c
@@ -2342,6 +2342,7 @@ S_sublex_push(pTHX)
SAVEI32(PL_lex_casemods);
SAVEI32(PL_lex_starts);
SAVEI8(PL_lex_state);
+ SAVEI8(PL_lex_defer);
SAVESPTR(PL_lex_repl);
SAVEVPTR(PL_lex_inpat);
SAVEI16(PL_lex_inwhat);