xref: /aosp_15_r20/external/protobuf/third_party/utf8_range/naive.c (revision 1b3f573f81763fcece89efc2b6a5209149e44ab8)
1 #include <stdio.h>
2 
3 /*
4  * http://www.unicode.org/versions/Unicode6.0.0/ch03.pdf - page 94
5  *
6  * Table 3-7. Well-Formed UTF-8 Byte Sequences
7  *
8  * +--------------------+------------+-------------+------------+-------------+
9  * | Code Points        | First Byte | Second Byte | Third Byte | Fourth Byte |
10  * +--------------------+------------+-------------+------------+-------------+
11  * | U+0000..U+007F     | 00..7F     |             |            |             |
12  * +--------------------+------------+-------------+------------+-------------+
13  * | U+0080..U+07FF     | C2..DF     | 80..BF      |            |             |
14  * +--------------------+------------+-------------+------------+-------------+
15  * | U+0800..U+0FFF     | E0         | A0..BF      | 80..BF     |             |
16  * +--------------------+------------+-------------+------------+-------------+
17  * | U+1000..U+CFFF     | E1..EC     | 80..BF      | 80..BF     |             |
18  * +--------------------+------------+-------------+------------+-------------+
19  * | U+D000..U+D7FF     | ED         | 80..9F      | 80..BF     |             |
20  * +--------------------+------------+-------------+------------+-------------+
21  * | U+E000..U+FFFF     | EE..EF     | 80..BF      | 80..BF     |             |
22  * +--------------------+------------+-------------+------------+-------------+
23  * | U+10000..U+3FFFF   | F0         | 90..BF      | 80..BF     | 80..BF      |
24  * +--------------------+------------+-------------+------------+-------------+
25  * | U+40000..U+FFFFF   | F1..F3     | 80..BF      | 80..BF     | 80..BF      |
26  * +--------------------+------------+-------------+------------+-------------+
27  * | U+100000..U+10FFFF | F4         | 80..8F      | 80..BF     | 80..BF      |
28  * +--------------------+------------+-------------+------------+-------------+
29  */
30 
31 /* Return 0 - success,  >0 - index(1 based) of first error char */
utf8_naive(const unsigned char * data,int len)32 int utf8_naive(const unsigned char *data, int len)
33 {
34     int err_pos = 1;
35 
36     while (len) {
37         int bytes;
38         const unsigned char byte1 = data[0];
39 
40         /* 00..7F */
41         if (byte1 <= 0x7F) {
42             bytes = 1;
43         /* C2..DF, 80..BF */
44         } else if (len >= 2 && byte1 >= 0xC2 && byte1 <= 0xDF &&
45                 (signed char)data[1] <= (signed char)0xBF) {
46             bytes = 2;
47         } else if (len >= 3) {
48             const unsigned char byte2 = data[1];
49 
50             /* Is byte2, byte3 between 0x80 ~ 0xBF */
51             const int byte2_ok = (signed char)byte2 <= (signed char)0xBF;
52             const int byte3_ok = (signed char)data[2] <= (signed char)0xBF;
53 
54             if (byte2_ok && byte3_ok &&
55                      /* E0, A0..BF, 80..BF */
56                     ((byte1 == 0xE0 && byte2 >= 0xA0) ||
57                      /* E1..EC, 80..BF, 80..BF */
58                      (byte1 >= 0xE1 && byte1 <= 0xEC) ||
59                      /* ED, 80..9F, 80..BF */
60                      (byte1 == 0xED && byte2 <= 0x9F) ||
61                      /* EE..EF, 80..BF, 80..BF */
62                      (byte1 >= 0xEE && byte1 <= 0xEF))) {
63                 bytes = 3;
64             } else if (len >= 4) {
65                 /* Is byte4 between 0x80 ~ 0xBF */
66                 const int byte4_ok = (signed char)data[3] <= (signed char)0xBF;
67 
68                 if (byte2_ok && byte3_ok && byte4_ok &&
69                          /* F0, 90..BF, 80..BF, 80..BF */
70                         ((byte1 == 0xF0 && byte2 >= 0x90) ||
71                          /* F1..F3, 80..BF, 80..BF, 80..BF */
72                          (byte1 >= 0xF1 && byte1 <= 0xF3) ||
73                          /* F4, 80..8F, 80..BF, 80..BF */
74                          (byte1 == 0xF4 && byte2 <= 0x8F))) {
75                     bytes = 4;
76                 } else {
77                     return err_pos;
78                 }
79             } else {
80                 return err_pos;
81             }
82         } else {
83             return err_pos;
84         }
85 
86         len -= bytes;
87         err_pos += bytes;
88         data += bytes;
89     }
90 
91     return 0;
92 }
93