diff options
author | David Mitchell <davem@iabyn.com> | 2013-04-10 16:10:28 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2013-04-12 11:29:55 +0100 |
commit | 4f3e2518850e12605980071a25c189c30710bcfd (patch) | |
tree | c6456af41e20ed20741f24701229cb38bb4582d1 /toke.c | |
parent | 3a54fd60e3d777bf86f4eec331b79a61c23d8393 (diff) | |
download | perl-4f3e2518850e12605980071a25c189c30710bcfd.tar.gz |
fix runtime /(?{})/ with overload::constant qr
There are two issues fixed here.
First, when a pattern has a run-time code-block included, such as
$code = '(?{...})'
/foo$code/
the mechanism used to parse those run-time blocks: of feeding the
resultant pattern into a call to eval_sv() with the string
qr'foo(?{...})'
and then extracting out any resulting opcode trees from the returned
qr object -- suffered from the re-parsed qr'..' also being subject to
overload:constant qr processing, which could result in Bad Things
happening.
Since we now have the PL_parser->lex_re_reparsing flag in scope throughout
the parsing of the pattern, this is easy to detect and avoid.
The second issue is a mechanism to avoid recursion when getting false
positives in S_has_runtime_code() for code like '[(?{})]'.
For patterns like this, we would suspect that the pattern may have code
(even though it doesn't), so feed it into qr'...' and reparse, and
again it looks like runtime code, so feed it in, rinse and repeat.
The thing to stop recursion was when we saw a qr with a single OP_CONST
string, we assumed it couldn't have any run-time component, and thus no
run-time code blocks.
However, this broke qr/foo/ in the presence of overload::constant qr
overloading, which could convert foo into a string containing code blocks.
The fix for this is to change the recursion-avoidance mechanism (in a way
which also turns out to be simpler too). Basically, when we fake up a
qr'...' and eval it, we turn off any 'use re eval' in scope: its not
needed, since we know the .... will be a constant string without any
overloading. Then we use the lack of 'use re eval' in scope to
skip calling S_has_runtime_code() and just assume that the code has no
run-time patterns (if it has, then eventually the regex parser will
rightly complain about 'Eval-group not allowed at runtime').
This commit also adds some fairly comprehensive tests for this.
Diffstat (limited to 'toke.c')
-rw-r--r-- | toke.c | 4 |
1 files changed, 3 insertions, 1 deletions
@@ -3755,7 +3755,9 @@ S_scan_const(pTHX_ char *start) /* return the substring (via pl_yylval) only if we parsed anything */ if (s > PL_bufptr) { SvREFCNT_inc_simple_void_NN(sv); - if ( PL_hints & ( PL_lex_inpat ? HINT_NEW_RE : HINT_NEW_STRING ) ) { + if ( (PL_hints & ( PL_lex_inpat ? HINT_NEW_RE : HINT_NEW_STRING )) + && ! PL_parser->lex_re_reparsing) + { const char *const key = PL_lex_inpat ? "qr" : "q"; const STRLEN keylen = PL_lex_inpat ? 2 : 1; const char *type; |