summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2018-01-12 16:21:48 +0000
committerDavid Mitchell <davem@iabyn.com>2018-01-19 13:45:20 +0000
commit6d63cc8e88a2b96ed80956f16c0978d790bf4411 (patch)
tree8f0a480fbc708d6d8752f40d4d7fd3adbee6ea16 /lib
parentc923a6996655868e1b5140e8e47c2514e006902b (diff)
downloadperl-6d63cc8e88a2b96ed80956f16c0978d790bf4411.tar.gz
tr///c: handle len(replacement charlist) > 32767
RT #132608 In the non-utf8 case, the /c (complement) flag to tr adds an implied \x{100}-\x{7fffffff} range to the search charlist. If the replacement list contains more chars than are paired with the 0-255 part of the search list, then the excess chars are stored in an extended part of the table. The excess char count was being stored as a short, which caused problems if the replacement list contained more than 32767 excess chars: either substituting the wrong char, or substituting for a char located up to 0xffff bytes in memory before the real translation table. So change it to SSize_t. Note that this is only a problem when the search and replacement charlists are non-utf8, the replacement list contains around 0x8000+ entries, and where the string being translated is utf8 with at least one codepoint >= U+8000.
Diffstat (limited to 'lib')
-rw-r--r--lib/B/Deparse.pm5
1 files changed, 4 insertions, 1 deletions
diff --git a/lib/B/Deparse.pm b/lib/B/Deparse.pm
index 5fc3d02e1f..0b4fafc012 100644
--- a/lib/B/Deparse.pm
+++ b/lib/B/Deparse.pm
@@ -58,6 +58,8 @@ our $AUTOLOAD;
use warnings ();
require feature;
+use Config;
+
BEGIN {
# List version-specific constants here.
# Easiest way to keep this code portable between version looks to
@@ -5607,7 +5609,8 @@ sub collapse {
sub tr_decode_byte {
my($table, $flags) = @_;
- my (@table) = unpack("s256sss*", $table);
+ my $ssize_t = $Config{ptrsize} == 8 ? 'q' : 'l';
+ my (@table) = unpack("s256${ssize_t}ss*", $table);
my ($excess_len, $repeat_char) = splice(@table, 256, 2);
my($c, $tr, @from, @to, @delfrom, $delhyphen);