[perl #114040] Fix here-docs in multiline re-evals
authorFather Chrysostomos <sprout@cpan.org>
Wed, 22 Aug 2012 21:07:44 +0000 (14:07 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Wed, 22 Aug 2012 22:53:27 +0000 (15:53 -0700)
commitdb4442662555874019f183661252bccd4e4ed138
tree80a3b6de5edef596b5eff49eabd365812269e391
parent486ffce2e3218c92f8211b19f0be2fc5532f8b57
[perl #114040] Fix here-docs in multiline re-evals

Commit 5097bf9b8 only partially fixed this, or, rather, did the
groundwork for fixing it.

If we have a pattern like this:

/(?{<<foo . baz
bar
foo
})/

Then PL_linestr contains this while we are parsing the block:

"(?{<<foo . baz\nbar\nfoo\n})"

The code for parsing a here-doc in a multiline PL_linestr buffer
(which applies to here-docs in string evals or in quote-like operat-
ors) likes to modify PL_linestr to contain everything after the
<<heredoc marker except the here-doc body, which has been stolen (but
it oddly includes the last character of the marker, which does not
matter, as PL_bufptr is set to PL_linestart+1):

"o . baz\n})"

The regexp block parsing code expects to be able to extract the entire
block (as a string) from PL_linestr after parsing it.  So it is not
helpful for S_scan_heredoc to go and modify it like that.

Before modifying PL_linestr, we can set aside a copy of the source
code (in PL_sublex_info.re_eval_str) from the beginning of the regexp
block to the end of PL_linestr, so that the regexp block code can
retrieve the original source from there.

We also adjust PL_sublex_info.re_eval_start so that at the end of the
regexp block PL_bufptr - PL_sublex_info.re_eval_start is the length of
the block.

Instead of clobbering PL_linestr, we can copy everything after the
here-doc to when the body begins.  And this for two reasons: it
requires less allocation (I would have made that change in the end
anyway, for efficiency), and it makes it easier to calculate how much
to subtract from re_eval_start.

This fix does not apply to here-docs in quotes in multiline string
evals, which crashes and always has.
perl.h
t/base/lex.t
toke.c