This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #128747] Fix line number bug with s//<<END/e
authorFather Chrysostomos <sprout@cpan.org>
Thu, 28 Jul 2016 05:09:42 +0000 (22:09 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Thu, 28 Jul 2016 05:10:17 +0000 (22:10 -0700)
commit2ca4363ddd9d355a31563ffe59eba09fcb54a708
tree771ad86aa6016a27b3c3d70e55c8d54625478a0c
parentf8c1150140e8f939dc97b3c3554dd59f92b7b0af
[perl #128747] Fix line number bug with s//<<END/e

In commit 6745174b561 I changed the multi_open and multi_close
parser pastruct members (known as PL_multi_open/close in toke.c) from
char to UV.

I failed to change the localization code in S_sublex_start:

    SAVEI8(PL_multi_close);

So on big-endian architectures only the most significant byte would be
localized.  That meant that effectively no localization would happen
for ASCII string delimiters.

In S_sublex_done:

LEAVE;
if (PL_multi_close == '<')
    PL_parser->herelines += l - PL_multi_end;

That LEAVE undoes the localization.  '<' for PL_multi_close is a spe-
cial value that can only happen for here-docs.   The ->herelines line
makes sure that line numbers are correct after a here-doc.

What ended up happening was that s//<<END/e would throw off line num-
bers after the here-doc body.  PL_multi_close would end up being set
to '<', not '/', when the lexer was finishing up the s///, so it
treated it like a here-doc and screwed things up.  This resulted in
the test failures in ticket #128747.

I found that we also had a bug on little-endian machines.  But to get
the localization of the *least* sigificant byte to screw things up,
you have to try something other than s//<<END/e:

use utf8;
<<END;
${
#line 57
qq || }
END
warn;  # line 59

Replace the pipes with lightning bolts:

use utf8;
<<END;
${
#line 57
qq ϟϟ }
END
warn;  # line 7

and you get line 7 instead of 59.  In this case, the inner construct
has a delimiter character whose code is > 255, but only the lower
8 bits get localized.  So when the localization unwinds, you get
ord("ϟ") & 0xff | ord("<") instead of just ord("<"), resulting in the
here-doc line number handling being skipped.

This commit fixes the localization and adds the little-endian test.
t/uni/parser.t
toke.c