summaryrefslogtreecommitdiff
path: root/toke.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2016-07-27 22:09:42 -0700
committerFather Chrysostomos <sprout@cpan.org>2016-07-27 22:10:17 -0700
commit2ca4363ddd9d355a31563ffe59eba09fcb54a708 (patch)
tree771ad86aa6016a27b3c3d70e55c8d54625478a0c /toke.c
parentf8c1150140e8f939dc97b3c3554dd59f92b7b0af (diff)
downloadperl-2ca4363ddd9d355a31563ffe59eba09fcb54a708.tar.gz
[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.
Diffstat (limited to 'toke.c')
-rw-r--r--toke.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/toke.c b/toke.c
index bf2ac05a21..2c87688df4 100644
--- a/toke.c
+++ b/toke.c
@@ -2365,7 +2365,7 @@ S_sublex_push(pTHX)
SAVEI32(PL_parser->herelines);
PL_parser->herelines = 0;
}
- SAVEI8(PL_multi_close);
+ SAVEIV(PL_multi_close);
SAVEPPTR(PL_bufptr);
SAVEPPTR(PL_bufend);
SAVEPPTR(PL_oldbufptr);