This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Move all the de-tainting logic for runperl into test.pl.
[perl5.git] / t / op / utftaint.t
1 #!./perl -T
2 # tests whether tainting works with UTF-8
3
4 BEGIN {
5     chdir 't' if -d 't';
6     @INC = qw(../lib);
7 }
8
9 use strict;
10 use Config;
11
12 # How to identify taint when you see it
13 sub any_tainted (@) {
14     not eval { join("",@_), kill 0; 1 };
15 }
16 sub tainted ($) {
17     any_tainted @_;
18 }
19
20 require './test.pl';
21 plan(tests => 3*10 + 3*8 + 2*16 + 2);
22
23 my $arg = $ENV{PATH}; # a tainted value
24 use constant UTF8 => "\x{1234}";
25
26 sub is_utf8 {
27     my $s = shift;
28     return 0xB6 != unpack('C', chr(0xB6).$s);
29 }
30
31 for my $ary ([ascii => 'perl'], [latin1 => "\xB6"], [utf8 => "\x{100}"]) {
32     my $encode = $ary->[0];
33     my $string = $ary->[1];
34
35     my $taint = $arg; substr($taint, 0) = $ary->[1];
36
37     is(tainted($taint), tainted($arg), "tainted: $encode, before test");
38
39     my $lconcat = $taint;
40        $lconcat .= UTF8;
41     is($lconcat, $string.UTF8, "compare: $encode, concat left");
42
43     is(tainted($lconcat), tainted($arg), "tainted: $encode, concat left");
44
45     my $rconcat = UTF8;
46        $rconcat .= $taint;
47     is($rconcat, UTF8.$string, "compare: $encode, concat right");
48
49     is(tainted($rconcat), tainted($arg), "tainted: $encode, concat right");
50
51     my $ljoin = join('!', $taint, UTF8);
52     is($ljoin, join('!', $string, UTF8), "compare: $encode, join left");
53
54     is(tainted($ljoin), tainted($arg), "tainted: $encode, join left");
55
56     my $rjoin = join('!', UTF8, $taint);
57     is($rjoin, join('!', UTF8, $string), "compare: $encode, join right");
58
59     is(tainted($rjoin), tainted($arg), "tainted: $encode, join right");
60
61     is(tainted($taint), tainted($arg), "tainted: $encode, after test");
62 }
63
64
65 for my $ary ([ascii => 'perl'], [latin1 => "\xB6"], [utf8 => "\x{100}"]) {
66     my $encode = $ary->[0];
67
68     my $utf8 = pack('U*') . $ary->[1];
69     my $byte = unpack('U0a*', $utf8);
70
71     my $taint = $arg; substr($taint, 0) = $utf8;
72     utf8::encode($taint);
73
74     is($taint, $byte, "compare: $encode, encode utf8");
75
76     is(pack('a*',$taint), pack('a*',$byte), "bytecmp: $encode, encode utf8");
77
78     ok(!is_utf8($taint), "is_utf8: $encode, encode utf8");
79
80     is(tainted($taint), tainted($arg), "tainted: $encode, encode utf8");
81
82     my $taint = $arg; substr($taint, 0) = $byte;
83     utf8::decode($taint);
84
85     is($taint, $utf8, "compare: $encode, decode byte");
86
87     is(pack('a*',$taint), pack('a*',$utf8), "bytecmp: $encode, decode byte");
88
89     is(is_utf8($taint), ($encode ne 'ascii'), "is_utf8: $encode, decode byte");
90
91     is(tainted($taint), tainted($arg), "tainted: $encode, decode byte");
92 }
93
94
95 for my $ary ([ascii => 'perl'], [latin1 => "\xB6"]) {
96     my $encode = $ary->[0];
97
98     my $up   = pack('U*') . $ary->[1];
99     my $down = pack("a*", $ary->[1]);
100
101     my $taint = $arg; substr($taint, 0) = $up;
102     utf8::upgrade($taint);
103
104     is($taint, $up, "compare: $encode, upgrade up");
105
106     is(pack('a*',$taint), pack('a*',$up), "bytecmp: $encode, upgrade up");
107
108     ok(is_utf8($taint), "is_utf8: $encode, upgrade up");
109
110     is(tainted($taint), tainted($arg), "tainted: $encode, upgrade up");
111
112     my $taint = $arg; substr($taint, 0) = $down;
113     utf8::upgrade($taint);
114
115     is($taint, $up, "compare: $encode, upgrade down");
116
117     is(pack('a*',$taint), pack('a*',$up), "bytecmp: $encode, upgrade down");
118
119     ok(is_utf8($taint), "is_utf8: $encode, upgrade down");
120
121     is(tainted($taint), tainted($arg), "tainted: $encode, upgrade down");
122
123     my $taint = $arg; substr($taint, 0) = $up;
124     utf8::downgrade($taint);
125
126     is($taint, $down, "compare: $encode, downgrade up");
127
128     is(pack('a*',$taint), pack('a*',$down), "bytecmp: $encode, downgrade up");
129
130     ok(!is_utf8($taint), "is_utf8: $encode, downgrade up");
131
132     is(tainted($taint), tainted($arg), "tainted: $encode, downgrade up");
133
134     my $taint = $arg; substr($taint, 0) = $down;
135     utf8::downgrade($taint);
136
137     is($taint, $down, "compare: $encode, downgrade down");
138
139     is(pack('a*',$taint), pack('a*',$down), "bytecmp: $encode, downgrade down");
140
141     ok(!is_utf8($taint), "is_utf8: $encode, downgrade down");
142
143     is(tainted($taint), tainted($arg), "tainted: $encode, downgrade down");
144 }
145
146 {
147     fresh_perl_is('$a = substr $^X, 0, 0; /\x{100}/i; /$a\x{100}/i || print q,ok,',
148                   'ok', {switches => ["-T", "-l"]},
149                   "matching a regexp is taint agnostic");
150
151     fresh_perl_is('$a = substr $^X, 0, 0; /$a\x{100}/i || print q,ok,',
152                   'ok', {switches => ["-T", "-l"]},
153                   "therefore swash_init should be taint agnostic");
154 }