xref: /unit/src/test/nxt_utf8_test.c (revision 384)
1*384Szelenkov@nginx.com 
2*384Szelenkov@nginx.com /*
3*384Szelenkov@nginx.com  * Copyright (C) Igor Sysoev
4*384Szelenkov@nginx.com  * Copyright (C) NGINX, Inc.
5*384Szelenkov@nginx.com  */
6*384Szelenkov@nginx.com 
7*384Szelenkov@nginx.com #include <nxt_main.h>
8*384Szelenkov@nginx.com #include "nxt_tests.h"
9*384Szelenkov@nginx.com 
10*384Szelenkov@nginx.com 
11*384Szelenkov@nginx.com #define NXT_UTF8_START_TEST  0xc2
12*384Szelenkov@nginx.com //#define NXT_UTF8_START_TEST  0
13*384Szelenkov@nginx.com 
14*384Szelenkov@nginx.com 
15*384Szelenkov@nginx.com static u_char  invalid[] = {
16*384Szelenkov@nginx.com 
17*384Szelenkov@nginx.com     /* Invalid first byte less than 0xc2. */
18*384Szelenkov@nginx.com     1, 0x80, 0x00, 0x00, 0x00,
19*384Szelenkov@nginx.com     1, 0xc0, 0x00, 0x00, 0x00,
20*384Szelenkov@nginx.com     2, 0xc0, 0x00, 0x00, 0x00,
21*384Szelenkov@nginx.com     3, 0xc0, 0x00, 0x00, 0x00,
22*384Szelenkov@nginx.com     4, 0xc0, 0x00, 0x00, 0x00,
23*384Szelenkov@nginx.com 
24*384Szelenkov@nginx.com     /* Invalid 0x0x110000 value. */
25*384Szelenkov@nginx.com     4, 0xf4, 0x90, 0x80, 0x80,
26*384Szelenkov@nginx.com 
27*384Szelenkov@nginx.com     /* Incomplete length. */
28*384Szelenkov@nginx.com     2, 0xe0, 0xaf, 0xb5, 0x00,
29*384Szelenkov@nginx.com 
30*384Szelenkov@nginx.com     /* Overlong values. */
31*384Szelenkov@nginx.com     2, 0xc0, 0x80, 0x00, 0x00,
32*384Szelenkov@nginx.com     2, 0xc1, 0xb3, 0x00, 0x00,
33*384Szelenkov@nginx.com     3, 0xe0, 0x80, 0x80, 0x00,
34*384Szelenkov@nginx.com     3, 0xe0, 0x81, 0xb3, 0x00,
35*384Szelenkov@nginx.com     3, 0xe0, 0x90, 0x9a, 0x00,
36*384Szelenkov@nginx.com     4, 0xf0, 0x80, 0x8a, 0x80,
37*384Szelenkov@nginx.com     4, 0xf0, 0x80, 0x81, 0xb3,
38*384Szelenkov@nginx.com     4, 0xf0, 0x80, 0xaf, 0xb5,
39*384Szelenkov@nginx.com };
40*384Szelenkov@nginx.com 
41*384Szelenkov@nginx.com 
42*384Szelenkov@nginx.com static nxt_int_t
43*384Szelenkov@nginx.com nxt_utf8_overlong(nxt_thread_t *thr, u_char *overlong, size_t len)
44*384Szelenkov@nginx.com {
45*384Szelenkov@nginx.com     u_char        *p, utf8[4];
46*384Szelenkov@nginx.com     size_t        size;
47*384Szelenkov@nginx.com     uint32_t      u, d;
48*384Szelenkov@nginx.com     nxt_uint_t    i;
49*384Szelenkov@nginx.com     const u_char  *pp;
50*384Szelenkov@nginx.com 
51*384Szelenkov@nginx.com     pp = overlong;
52*384Szelenkov@nginx.com 
53*384Szelenkov@nginx.com     d = nxt_utf8_decode(&pp, overlong + len);
54*384Szelenkov@nginx.com 
55*384Szelenkov@nginx.com     len = pp - overlong;
56*384Szelenkov@nginx.com 
57*384Szelenkov@nginx.com     if (d != 0xffffffff) {
58*384Szelenkov@nginx.com         p = nxt_utf8_encode(utf8, d);
59*384Szelenkov@nginx.com 
60*384Szelenkov@nginx.com         size = (p != NULL) ? p - utf8 : 0;
61*384Szelenkov@nginx.com 
62*384Szelenkov@nginx.com         if (len != size || nxt_memcmp(overlong, utf8, size) != 0) {
63*384Szelenkov@nginx.com 
64*384Szelenkov@nginx.com             u = 0;
65*384Szelenkov@nginx.com             for (i = 0; i < len; i++) {
66*384Szelenkov@nginx.com                 u = (u << 8) + overlong[i];
67*384Szelenkov@nginx.com             }
68*384Szelenkov@nginx.com 
69*384Szelenkov@nginx.com             nxt_log_alert(thr->log,
70*384Szelenkov@nginx.com                           "nxt_utf8_decode(%05uxD, %uz) failed: %05uxD, %uz",
71*384Szelenkov@nginx.com                           u, len, d, size);
72*384Szelenkov@nginx.com 
73*384Szelenkov@nginx.com             return NXT_ERROR;
74*384Szelenkov@nginx.com         }
75*384Szelenkov@nginx.com     }
76*384Szelenkov@nginx.com 
77*384Szelenkov@nginx.com     return NXT_OK;
78*384Szelenkov@nginx.com }
79*384Szelenkov@nginx.com 
80*384Szelenkov@nginx.com 
81*384Szelenkov@nginx.com nxt_int_t
82*384Szelenkov@nginx.com nxt_utf8_test(nxt_thread_t *thr)
83*384Szelenkov@nginx.com {
84*384Szelenkov@nginx.com     u_char        *p, utf8[4];
85*384Szelenkov@nginx.com     size_t        len;
86*384Szelenkov@nginx.com     int32_t       n;
87*384Szelenkov@nginx.com     uint32_t      u, d;
88*384Szelenkov@nginx.com     nxt_uint_t    i, k, l, m;
89*384Szelenkov@nginx.com     const u_char  *pp;
90*384Szelenkov@nginx.com 
91*384Szelenkov@nginx.com     nxt_thread_time_update(thr);
92*384Szelenkov@nginx.com 
93*384Szelenkov@nginx.com     nxt_log_error(NXT_LOG_NOTICE, thr->log, "utf8 test started");
94*384Szelenkov@nginx.com 
95*384Szelenkov@nginx.com     /* Test valid UTF-8. */
96*384Szelenkov@nginx.com 
97*384Szelenkov@nginx.com     for (u = 0; u < 0x110000; u++) {
98*384Szelenkov@nginx.com 
99*384Szelenkov@nginx.com         p = nxt_utf8_encode(utf8, u);
100*384Szelenkov@nginx.com 
101*384Szelenkov@nginx.com         if (p == NULL) {
102*384Szelenkov@nginx.com             nxt_log_alert(thr->log, "nxt_utf8_encode(%05uxD) failed", u);
103*384Szelenkov@nginx.com             return NXT_ERROR;
104*384Szelenkov@nginx.com         }
105*384Szelenkov@nginx.com 
106*384Szelenkov@nginx.com         pp = utf8;
107*384Szelenkov@nginx.com 
108*384Szelenkov@nginx.com         d = nxt_utf8_decode(&pp, p);
109*384Szelenkov@nginx.com 
110*384Szelenkov@nginx.com         if (u != d) {
111*384Szelenkov@nginx.com             nxt_log_alert(thr->log, "nxt_utf8_decode(%05uxD) failed: %05uxD",
112*384Szelenkov@nginx.com                           u, d);
113*384Szelenkov@nginx.com             return NXT_ERROR;
114*384Szelenkov@nginx.com         }
115*384Szelenkov@nginx.com     }
116*384Szelenkov@nginx.com 
117*384Szelenkov@nginx.com     /* Test some invalid UTF-8. */
118*384Szelenkov@nginx.com 
119*384Szelenkov@nginx.com     for (i = 0; i < sizeof(invalid); i += 5) {
120*384Szelenkov@nginx.com 
121*384Szelenkov@nginx.com         len = invalid[i];
122*384Szelenkov@nginx.com         utf8[0] = invalid[i + 1];
123*384Szelenkov@nginx.com         utf8[1] = invalid[i + 2];
124*384Szelenkov@nginx.com         utf8[2] = invalid[i + 3];
125*384Szelenkov@nginx.com         utf8[3] = invalid[i + 4];
126*384Szelenkov@nginx.com 
127*384Szelenkov@nginx.com         pp = utf8;
128*384Szelenkov@nginx.com 
129*384Szelenkov@nginx.com         d = nxt_utf8_decode(&pp, utf8 + len);
130*384Szelenkov@nginx.com 
131*384Szelenkov@nginx.com         if (d != 0xffffffff) {
132*384Szelenkov@nginx.com 
133*384Szelenkov@nginx.com             u = 0;
134*384Szelenkov@nginx.com             for (i = 0; i < len; i++) {
135*384Szelenkov@nginx.com                 u = (u << 8) + utf8[i];
136*384Szelenkov@nginx.com             }
137*384Szelenkov@nginx.com 
138*384Szelenkov@nginx.com             nxt_log_alert(thr->log,
139*384Szelenkov@nginx.com                           "nxt_utf8_decode(%05uxD, %uz) failed: %05uxD",
140*384Szelenkov@nginx.com                           u, len, d);
141*384Szelenkov@nginx.com             return NXT_ERROR;
142*384Szelenkov@nginx.com         }
143*384Szelenkov@nginx.com     }
144*384Szelenkov@nginx.com 
145*384Szelenkov@nginx.com     /* Test all overlong UTF-8. */
146*384Szelenkov@nginx.com 
147*384Szelenkov@nginx.com     for (i = NXT_UTF8_START_TEST; i < 256; i++) {
148*384Szelenkov@nginx.com         utf8[0] = i;
149*384Szelenkov@nginx.com 
150*384Szelenkov@nginx.com         if (nxt_utf8_overlong(thr, utf8, 1) != NXT_OK) {
151*384Szelenkov@nginx.com             return NXT_ERROR;
152*384Szelenkov@nginx.com         }
153*384Szelenkov@nginx.com 
154*384Szelenkov@nginx.com         for (k = 0; k < 256; k++) {
155*384Szelenkov@nginx.com             utf8[1] = k;
156*384Szelenkov@nginx.com 
157*384Szelenkov@nginx.com             if (nxt_utf8_overlong(thr, utf8, 2) != NXT_OK) {
158*384Szelenkov@nginx.com                 return NXT_ERROR;
159*384Szelenkov@nginx.com             }
160*384Szelenkov@nginx.com 
161*384Szelenkov@nginx.com             for (l = 0; l < 256; l++) {
162*384Szelenkov@nginx.com                 utf8[2] = l;
163*384Szelenkov@nginx.com 
164*384Szelenkov@nginx.com                 if (nxt_utf8_overlong(thr, utf8, 3) != NXT_OK) {
165*384Szelenkov@nginx.com                     return NXT_ERROR;
166*384Szelenkov@nginx.com                 }
167*384Szelenkov@nginx.com 
168*384Szelenkov@nginx.com                 for (m = 0; m < 256; m++) {
169*384Szelenkov@nginx.com                     utf8[3] = m;
170*384Szelenkov@nginx.com 
171*384Szelenkov@nginx.com                     if (nxt_utf8_overlong(thr, utf8, 4) != NXT_OK) {
172*384Szelenkov@nginx.com                         return NXT_ERROR;
173*384Szelenkov@nginx.com                     }
174*384Szelenkov@nginx.com                 }
175*384Szelenkov@nginx.com             }
176*384Szelenkov@nginx.com         }
177*384Szelenkov@nginx.com     }
178*384Szelenkov@nginx.com 
179*384Szelenkov@nginx.com     n = nxt_utf8_casecmp((u_char *) "ABC АБВ ΑΒΓ",
180*384Szelenkov@nginx.com                          (u_char *) "abc абв αβγ",
181*384Szelenkov@nginx.com                              sizeof("ABC АБВ ΑΒΓ") - 1,
182*384Szelenkov@nginx.com                              sizeof("abc абв αβγ") - 1);
183*384Szelenkov@nginx.com 
184*384Szelenkov@nginx.com     if (n != 0) {
185*384Szelenkov@nginx.com         nxt_log_alert(thr->log, "nxt_utf8_casecmp() failed");
186*384Szelenkov@nginx.com         return NXT_ERROR;
187*384Szelenkov@nginx.com     }
188*384Szelenkov@nginx.com 
189*384Szelenkov@nginx.com     nxt_log_error(NXT_LOG_NOTICE, thr->log, "utf8 test passed");
190*384Szelenkov@nginx.com     return NXT_OK;
191*384Szelenkov@nginx.com }
192