|
1 | 1 | #include "config.h" |
2 | 2 | #include <assert.h> |
| 3 | +#include <ccan/array_size/array_size.h> |
3 | 4 | #include <common/amount.h> |
4 | 5 | #include <common/pseudorand.h> |
5 | 6 | #include <common/setup.h> |
@@ -106,47 +107,67 @@ void towire_u8_array(u8 **pptr UNNEEDED, const u8 *arr UNNEEDED, size_t num UNNE |
106 | 107 | static void test_valid(void) |
107 | 108 | { |
108 | 109 | assert(utf8_check("hello world", strlen("hello world"))); |
| 110 | + assert(utf8_check_text("hello world", strlen("hello world"))); |
109 | 111 |
|
110 | 112 | { |
111 | 113 | static const u8 nansensu[] = { |
112 | 114 | 0xe3, 0x83, 0x8a, 0xe3, 0x83, 0xb3, 0xe3, 0x82, |
113 | 115 | 0xbb, 0xe3, 0x83, 0xb3, 0xe3, 0x82, 0xb9 |
114 | 116 | }; |
115 | 117 | assert(utf8_check(nansensu, sizeof(nansensu))); |
| 118 | + assert(utf8_check_text(nansensu, sizeof(nansensu))); |
116 | 119 | } |
117 | 120 |
|
118 | 121 | assert(utf8_check("", 0)); |
| 122 | + assert(utf8_check_text("", 0)); |
119 | 123 | } |
120 | 124 |
|
121 | | -static void test_banned(void) |
| 125 | +/* NUL, surrogates and overlong encodings are rejected by ccan/utf8 |
| 126 | + * itself (utf8_decode()), regardless of category filtering - even |
| 127 | + * plain utf8_check() rejects those */ |
| 128 | +static void test_encoding_banned(void) |
122 | 129 | { |
123 | 130 | static const u8 embedded_nul[] = { 'a', 0x00, 'b' }; |
124 | 131 | assert(!utf8_check(embedded_nul, sizeof(embedded_nul))); |
| 132 | + assert(!utf8_check_text(embedded_nul, sizeof(embedded_nul))); |
| 133 | +} |
125 | 134 |
|
126 | | - assert(!utf8_check("a\tb", 3)); |
127 | | - |
| 135 | +/* Codepoints in Unicode categories Cc/Cf/Co/Cn are valid UTF-8 |
| 136 | + * encoding (plain utf8_check() accepts them - it's used for general |
| 137 | + * JSON-RPC input, datastore, which shouldn't be restricted this |
| 138 | + * way), but utf8_check_text() must reject them for protocol text |
| 139 | + * fields */ |
| 140 | +static void test_text_banned(void) |
| 141 | +{ |
| 142 | + static const u8 tab[] = { 'a', '\t', 'b' }; |
128 | 143 | static const u8 del[] = { 'a', 0x7f, 'b' }; |
129 | | - assert(!utf8_check(del, sizeof(del))); |
130 | | - |
131 | 144 | static const u8 c1_control[] = { 'a', 0xc2, 0x85, 'b' }; |
132 | | - assert(!utf8_check(c1_control, sizeof(c1_control))); |
133 | | - |
134 | 145 | static const u8 rtl_override[] = { 'a', 0xe2, 0x80, 0xae, 'b' }; |
135 | | - assert(!utf8_check(rtl_override, sizeof(rtl_override))); |
136 | | - |
137 | 146 | static const u8 private_use[] = { 'a', 0xee, 0x80, 0x80, 'b' }; |
138 | | - assert(!utf8_check(private_use, sizeof(private_use))); |
139 | | - |
140 | 147 | static const u8 unassigned[] = { 'a', 0xcd, 0xb8, 'b' }; |
141 | | - assert(!utf8_check(unassigned, sizeof(unassigned))); |
| 148 | + static const u8 *cases[] = { |
| 149 | + tab, del, c1_control, rtl_override, private_use, unassigned |
| 150 | + }; |
| 151 | + static const size_t lens[] = { |
| 152 | + sizeof(tab), sizeof(del), sizeof(c1_control), |
| 153 | + sizeof(rtl_override), sizeof(private_use), sizeof(unassigned) |
| 154 | + }; |
| 155 | + |
| 156 | + for (size_t i = 0; i < ARRAY_SIZE(cases); i++) { |
| 157 | + /* Plain utf8_check() stays permissive - valid encoding */ |
| 158 | + assert(utf8_check(cases[i], lens[i])); |
| 159 | + /* utf8_check_text() rejects the banned category */ |
| 160 | + assert(!utf8_check_text(cases[i], lens[i])); |
| 161 | + } |
142 | 162 | } |
143 | 163 |
|
144 | 164 | int main(int argc, char *argv[]) |
145 | 165 | { |
146 | 166 | common_setup(argv[0]); |
147 | 167 |
|
148 | 168 | test_valid(); |
149 | | - test_banned(); |
| 169 | + test_encoding_banned(); |
| 170 | + test_text_banned(); |
150 | 171 |
|
151 | 172 | common_shutdown(); |
152 | 173 | } |
0 commit comments