Commit | Line | Data |
---|---|---|
a9917092 JH |
1 | #!./perl |
2 | ||
3 | BEGIN { | |
4 | chdir 't' if -d 't'; | |
5 | @INC = '../lib'; | |
6 | } | |
7 | ||
3b0e0cb6 | 8 | no utf8; |
ffc61ed2 | 9 | |
a9917092 JH |
10 | print "1..78\n"; |
11 | ||
12 | my $test = 1; | |
13 | ||
14 | # This table is based on Markus Kuhn's UTF-8 Decode Stress Tester, | |
15 | # http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt, | |
16 | # version dated 2000-09-02. | |
17 | ||
3b0e0cb6 JH |
18 | # We use the \x notation instead of raw binary bytes for \x00-\x1f\x7f-\xff |
19 | # because e.g. many patch programs have issues with binary data. | |
a9917092 JH |
20 | |
21 | my @MK = split(/\n/, <<__EOMK__); | |
22 | 1 Correct UTF-8 | |
3b0e0cb6 | 23 | 1.1.1 y "\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5" - 11 ce:ba:e1:bd:b9:cf:83:ce:bc:ce:b5 5 |
a9917092 JH |
24 | 2 Boundary conditions |
25 | 2.1 First possible sequence of certain length | |
3b0e0cb6 JH |
26 | 2.1.1 y "\x00" 0 1 00 1 |
27 | 2.1.2 y "\xc2\x80" 80 2 c2:80 1 | |
28 | 2.1.3 y "\xe0\xa0\x80" 800 3 e0:a0:80 1 | |
29 | 2.1.4 y "\xf0\x90\x80\x80" 10000 4 f0:90:80:80 1 | |
30 | 2.1.5 y "\xf8\x88\x80\x80\x80" 200000 5 f8:88:80:80:80 1 | |
31 | 2.1.6 y "\xfc\x84\x80\x80\x80\x80" 4000000 6 fc:84:80:80:80:80 1 | |
a9917092 | 32 | 2.2 Last possible sequence of certain length |
3b0e0cb6 JH |
33 | 2.2.1 y "\x7f" 7f 1 7f 1 |
34 | 2.2.2 y "\xdf\xbf" 7ff 2 df:bf 1 | |
a9917092 | 35 | # The ffff is illegal unless UTF8_ALLOW_FFFF |
3b0e0cb6 JH |
36 | 2.2.3 n "\xef\xbf\xbf" ffff 3 ef:bf:bf 1 character 0xffff |
37 | 2.2.4 y "\xf7\xbf\xbf\xbf" 1fffff 4 f7:bf:bf:bf 1 | |
38 | 2.2.5 y "\xfb\xbf\xbf\xbf\xbf" 3ffffff 5 fb:bf:bf:bf:bf 1 | |
39 | 2.2.6 y "\xfd\xbf\xbf\xbf\xbf\xbf" 7fffffff 6 fd:bf:bf:bf:bf:bf 1 | |
a9917092 | 40 | 2.3 Other boundary conditions |
3b0e0cb6 JH |
41 | 2.3.1 y "\xed\x9f\xbf" d7ff 3 ed:9f:bf 1 |
42 | 2.3.2 y "\xee\x80\x80" e000 3 ee:80:80 1 | |
43 | 2.3.3 y "\xef\xbf\xbd" fffd 3 ef:bf:bd 1 | |
44 | 2.3.4 y "\xf4\x8f\xbf\xbf" 10ffff 4 f4:8f:bf:bf 1 | |
45 | 2.3.5 y "\xf4\x90\x80\x80" 110000 4 f4:90:80:80 1 | |
a9917092 JH |
46 | 3 Malformed sequences |
47 | 3.1 Unexpected continuation bytes | |
3b0e0cb6 JH |
48 | 3.1.1 n "\x80" - 1 80 - unexpected continuation byte 0x80 |
49 | 3.1.2 n "\xbf" - 1 bf - unexpected continuation byte 0xbf | |
50 | 3.1.3 n "\x80\xbf" - 2 80:bf - unexpected continuation byte 0x80 | |
51 | 3.1.4 n "\x80\xbf\x80" - 3 80:bf:80 - unexpected continuation byte 0x80 | |
52 | 3.1.5 n "\x80\xbf\x80\xbf" - 4 80:bf:80:bf - unexpected continuation byte 0x80 | |
53 | 3.1.6 n "\x80\xbf\x80\xbf\x80" - 5 80:bf:80:bf:80 - unexpected continuation byte 0x80 | |
54 | 3.1.7 n "\x80\xbf\x80\xbf\x80\xbf" - 6 80:bf:80:bf:80:bf - unexpected continuation byte 0x80 | |
55 | 3.1.8 n "\x80\xbf\x80\xbf\x80\xbf\x80" - 7 80:bf:80:bf:80:bf:80 - unexpected continuation byte 0x80 | |
56 | 3.1.9 n "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" - 64 80:81:82:83:84:85:86:87:88:89:8a:8b:8c:8d:8e:8f:90:91:92:93:94:95:96:97:98:99:9a:9b:9c:9d:9e:9f:a0:a1:a2:a3:a4:a5:a6:a7:a8:a9:aa:ab:ac:ad:ae:af:b0:b1:b2:b3:b4:b5:b6:b7:b8:b9:ba:bb:bc:bd:be:bf - unexpected continuation byte 0x80 | |
a9917092 | 57 | 3.2 Lonely start characters |
3b0e0cb6 JH |
58 | 3.2.1 n "\xc0 \xc1 \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf " - 64 c0:20:c1:20:c2:20:c3:20:c4:20:c5:20:c6:20:c7:20:c8:20:c9:20:ca:20:cb:20:cc:20:cd:20:ce:20:cf:20:d0:20:d1:20:d2:20:d3:20:d4:20:d5:20:d6:20:d7:20:d8:20:d9:20:da:20:db:20:dc:20:dd:20:de:20:df:20 - unexpected non-continuation byte 0x20 after start byte 0xc0 |
59 | 3.2.2 n "\xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef " - 32 e0:20:e1:20:e2:20:e3:20:e4:20:e5:20:e6:20:e7:20:e8:20:e9:20:ea:20:eb:20:ec:20:ed:20:ee:20:ef:20 - unexpected non-continuation byte 0x20 after start byte 0xe0 | |
60 | 3.2.3 n "\xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 " - 16 f0:20:f1:20:f2:20:f3:20:f4:20:f5:20:f6:20:f7:20 - unexpected non-continuation byte 0x20 after start byte 0xf0 | |
61 | 3.2.4 n "\xf8 \xf9 \xfa \xfb " - 8 f8:20:f9:20:fa:20:fb:20 - unexpected non-continuation byte 0x20 after start byte 0xf8 | |
62 | 3.2.5 n "\xfc \xfd " - 4 fc:20:fd:20 - unexpected non-continuation byte 0x20 after start byte 0xfc | |
a9917092 | 63 | 3.3 Sequences with last continuation byte missing |
3b0e0cb6 JH |
64 | 3.3.1 n "\xc0" - 1 c0 - 1 byte, need 2 |
65 | 3.3.2 n "\xe0\x80" - 2 e0:80 - 2 bytes, need 3 | |
66 | 3.3.3 n "\xf0\x80\x80" - 3 f0:80:80 - 3 bytes, need 4 | |
67 | 3.3.4 n "\xf8\x80\x80\x80" - 4 f8:80:80:80 - 4 bytes, need 5 | |
68 | 3.3.5 n "\xfc\x80\x80\x80\x80" - 5 fc:80:80:80:80 - 5 bytes, need 6 | |
69 | 3.3.6 n "\xdf" - 1 df - 1 byte, need 2 | |
70 | 3.3.7 n "\xef\xbf" - 2 ef:bf - 2 bytes, need 3 | |
71 | 3.3.8 n "\xf7\xbf\xbf" - 3 f7:bf:bf - 3 bytes, need 4 | |
72 | 3.3.9 n "\xfb\xbf\xbf\xbf" - 4 fb:bf:bf:bf - 4 bytes, need 5 | |
73 | 3.3.10 n "\xfd\xbf\xbf\xbf\xbf" - 5 fd:bf:bf:bf:bf - 5 bytes, need 6 | |
a9917092 | 74 | 3.4 Concatenation of incomplete sequences |
3b0e0cb6 | 75 | 3.4.1 n "\xc0\xe0\x80\xf0\x80\x80\xf8\x80\x80\x80\xfc\x80\x80\x80\x80\xdf\xef\xbf\xf7\xbf\xbf\xfb\xbf\xbf\xbf\xfd\xbf\xbf\xbf\xbf" - 30 c0:e0:80:f0:80:80:f8:80:80:80:fc:80:80:80:80:df:ef:bf:f7:bf:bf:fb:bf:bf:bf:fd:bf:bf:bf:bf - unexpected non-continuation byte 0xe0 after start byte 0xc0 |
a9917092 | 76 | 3.5 Impossible bytes |
3b0e0cb6 JH |
77 | 3.5.1 n "\xfe" - 1 fe - byte 0xfe |
78 | 3.5.2 n "\xff" - 1 ff - byte 0xff | |
79 | 3.5.3 n "\xfe\xfe\xff\xff" - 4 fe:fe:ff:ff - byte 0xfe | |
a9917092 JH |
80 | 4 Overlong sequences |
81 | 4.1 Examples of an overlong ASCII character | |
3b0e0cb6 JH |
82 | 4.1.1 n "\xc0\xaf" - 2 c0:af - 2 bytes, need 1 |
83 | 4.1.2 n "\xe0\x80\xaf" - 3 e0:80:af - 3 bytes, need 1 | |
84 | 4.1.3 n "\xf0\x80\x80\xaf" - 4 f0:80:80:af - 4 bytes, need 1 | |
85 | 4.1.4 n "\xf8\x80\x80\x80\xaf" - 5 f8:80:80:80:af - 5 bytes, need 1 | |
86 | 4.1.5 n "\xfc\x80\x80\x80\x80\xaf" - 6 fc:80:80:80:80:af - 6 bytes, need 1 | |
a9917092 | 87 | 4.2 Maximum overlong sequences |
3b0e0cb6 JH |
88 | 4.2.1 n "\xc1\xbf" - 2 c1:bf - 2 bytes, need 1 |
89 | 4.2.2 n "\xe0\x9f\xbf" - 3 e0:9f:bf - 3 bytes, need 2 | |
90 | 4.2.3 n "\xf0\x8f\xbf\xbf" - 4 f0:8f:bf:bf - 4 bytes, need 3 | |
91 | 4.2.4 n "\xf8\x87\xbf\xbf\xbf" - 5 f8:87:bf:bf:bf - 5 bytes, need 4 | |
92 | 4.2.5 n "\xfc\x83\xbf\xbf\xbf\xbf" - 6 fc:83:bf:bf:bf:bf - 6 bytes, need 5 | |
a9917092 | 93 | 4.3 Overlong representation of the NUL character |
3b0e0cb6 JH |
94 | 4.3.1 n "\xc0\x80" - 2 c0:80 - 2 bytes, need 1 |
95 | 4.3.2 n "\xe0\x80\x80" - 3 e0:80:80 - 3 bytes, need 1 | |
96 | 4.3.3 n "\xf0\x80\x80\x80" - 4 f0:80:80:80 - 4 bytes, need 1 | |
97 | 4.3.4 n "\xf8\x80\x80\x80\x80" - 5 f8:80:80:80:80 - 5 bytes, need 1 | |
98 | 4.3.5 n "\xfc\x80\x80\x80\x80\x80" - 6 fc:80:80:80:80:80 - 6 bytes, need 1 | |
a9917092 JH |
99 | 5 Illegal code positions |
100 | 5.1 Single UTF-16 surrogates | |
3b0e0cb6 JH |
101 | 5.1.1 n "\xed\xa0\x80" - 3 ed:a0:80 - UTF-16 surrogate 0xd800 |
102 | 5.1.2 n "\xed\xad\xbf" - 3 ed:ad:bf - UTF-16 surrogate 0xdb7f | |
103 | 5.1.3 n "\xed\xae\x80" - 3 ed:ae:80 - UTF-16 surrogate 0xdb80 | |
104 | 5.1.4 n "\xed\xaf\xbf" - 3 ed:af:bf - UTF-16 surrogate 0xdbff | |
105 | 5.1.5 n "\xed\xb0\x80" - 3 ed:b0:80 - UTF-16 surrogate 0xdc00 | |
106 | 5.1.6 n "\xed\xbe\x80" - 3 ed:be:80 - UTF-16 surrogate 0xdf80 | |
107 | 5.1.7 n "\xed\xbf\xbf" - 3 ed:bf:bf - UTF-16 surrogate 0xdfff | |
a9917092 | 108 | 5.2 Paired UTF-16 surrogates |
3b0e0cb6 JH |
109 | 5.2.1 n "\xed\xa0\x80\xed\xb0\x80" - 6 ed:a0:80:ed:b0:80 - UTF-16 surrogate 0xd800 |
110 | 5.2.2 n "\xed\xa0\x80\xed\xbf\xbf" - 6 ed:a0:80:ed:bf:bf - UTF-16 surrogate 0xd800 | |
111 | 5.2.3 n "\xed\xad\xbf\xed\xb0\x80" - 6 ed:ad:bf:ed:b0:80 - UTF-16 surrogate 0xdb7f | |
112 | 5.2.4 n "\xed\xad\xbf\xed\xbf\xbf" - 6 ed:ad:bf:ed:bf:bf - UTF-16 surrogate 0xdb7f | |
113 | 5.2.5 n "\xed\xae\x80\xed\xb0\x80" - 6 ed:ae:80:ed:b0:80 - UTF-16 surrogate 0xdb80 | |
114 | 5.2.6 n "\xed\xae\x80\xed\xbf\xbf" - 6 ed:ae:80:ed:bf:bf - UTF-16 surrogate 0xdb80 | |
115 | 5.2.7 n "\xed\xaf\xbf\xed\xb0\x80" - 6 ed:af:bf:ed:b0:80 - UTF-16 surrogate 0xdbff | |
116 | 5.2.8 n "\xed\xaf\xbf\xed\xbf\xbf" - 6 ed:af:bf:ed:bf:bf - UTF-16 surrogate 0xdbff | |
a9917092 | 117 | 5.3 Other illegal code positions |
3b0e0cb6 | 118 | 5.3.1 n "\xef\xbf\xbe" - 3 ef:bf:be - byte order mark 0xfffe |
a9917092 | 119 | # The ffff is illegal unless UTF8_ALLOW_FFFF |
3b0e0cb6 | 120 | 5.3.2 n "\xef\xbf\xbf" - 3 ef:bf:bf - character 0xffff |
a9917092 JH |
121 | __EOMK__ |
122 | ||
123 | # 104..181 | |
124 | { | |
125 | my $WARNCNT; | |
126 | my $id; | |
127 | ||
128 | local $SIG{__WARN__} = | |
129 | sub { | |
421a8bf2 | 130 | print "# $id: @_"; |
a9917092 JH |
131 | $WARNCNT++; |
132 | $WARNMSG = "@_"; | |
133 | }; | |
134 | ||
135 | sub moan { | |
136 | print "$id: @_"; | |
137 | } | |
138 | ||
139 | sub test_unpack_U { | |
140 | $WARNCNT = 0; | |
141 | $WARNMSG = ""; | |
142 | unpack('U*', $_[0]); | |
143 | } | |
144 | ||
145 | for (@MK) { | |
146 | if (/^(?:\d+(?:\.\d+)?)\s/ || /^#/) { | |
147 | # print "# $_\n"; | |
148 | } elsif (/^(\d+\.\d+\.\d+[bu]?)\s+([yn])\s+"(.+)"\s+([0-9a-f]{1,8}|-)\s+(\d+)\s+([0-9a-f]{2}(?::[0-9a-f]{2})*)(?:\s+((?:\d+|-)(?:\s+(.+))?))?$/) { | |
149 | $id = $1; | |
150 | my ($okay, $bytes, $Unicode, $byteslen, $hex, $charslen, $error) = | |
151 | ($2, $3, $4, $5, $6, $7, $8); | |
152 | my @hex = split(/:/, $hex); | |
153 | unless (@hex == $byteslen) { | |
154 | my $nhex = @hex; | |
155 | moan "amount of hex ($nhex) not equal to byteslen ($byteslen)\n"; | |
156 | } | |
157 | { | |
158 | use bytes; | |
159 | my $bytesbyteslen = length($bytes); | |
160 | unless ($bytesbyteslen == $byteslen) { | |
161 | moan "bytes length() ($bytesbyteslen) not equal to $byteslen\n"; | |
162 | } | |
163 | } | |
164 | if ($okay eq 'y') { | |
165 | test_unpack_U($bytes); | |
166 | if ($WARNCNT) { | |
167 | moan "unpack('U*') false negative\n"; | |
168 | print "not "; | |
169 | } | |
170 | } elsif ($okay eq 'n') { | |
171 | test_unpack_U($bytes); | |
172 | if ($WARNCNT == 0 || ($error ne '' && $WARNMSG !~ /$error/)) { | |
173 | moan "unpack('U*') false positive\n"; | |
174 | print "not "; | |
175 | } | |
176 | } | |
177 | print "ok $test\n"; | |
178 | $test++; | |
179 | } else { | |
180 | moan "unknown format\n"; | |
181 | } | |
182 | } | |
183 | } |