]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
13471436 | 2 | |
dccca82b LP |
3 | #include <errno.h> |
4 | ||
13471436 RC |
5 | #include "alloc-util.h" |
6 | #include "hexdecoct.h" | |
7 | #include "macro.h" | |
8 | #include "string-util.h" | |
9 | ||
10 | static void test_hexchar(void) { | |
11 | assert_se(hexchar(0xa) == 'a'); | |
12 | assert_se(hexchar(0x0) == '0'); | |
13 | } | |
14 | ||
15 | static void test_unhexchar(void) { | |
16 | assert_se(unhexchar('a') == 0xA); | |
17 | assert_se(unhexchar('A') == 0xA); | |
18 | assert_se(unhexchar('0') == 0x0); | |
19 | } | |
20 | ||
21 | static void test_base32hexchar(void) { | |
22 | assert_se(base32hexchar(0) == '0'); | |
23 | assert_se(base32hexchar(9) == '9'); | |
24 | assert_se(base32hexchar(10) == 'A'); | |
25 | assert_se(base32hexchar(31) == 'V'); | |
26 | } | |
27 | ||
28 | static void test_unbase32hexchar(void) { | |
29 | assert_se(unbase32hexchar('0') == 0); | |
30 | assert_se(unbase32hexchar('9') == 9); | |
31 | assert_se(unbase32hexchar('A') == 10); | |
32 | assert_se(unbase32hexchar('V') == 31); | |
33 | assert_se(unbase32hexchar('=') == -EINVAL); | |
34 | } | |
35 | ||
36 | static void test_base64char(void) { | |
37 | assert_se(base64char(0) == 'A'); | |
38 | assert_se(base64char(26) == 'a'); | |
39 | assert_se(base64char(63) == '/'); | |
40 | } | |
41 | ||
42 | static void test_unbase64char(void) { | |
43 | assert_se(unbase64char('A') == 0); | |
44 | assert_se(unbase64char('Z') == 25); | |
45 | assert_se(unbase64char('a') == 26); | |
46 | assert_se(unbase64char('z') == 51); | |
47 | assert_se(unbase64char('0') == 52); | |
48 | assert_se(unbase64char('9') == 61); | |
49 | assert_se(unbase64char('+') == 62); | |
50 | assert_se(unbase64char('/') == 63); | |
51 | assert_se(unbase64char('=') == -EINVAL); | |
52 | } | |
53 | ||
54 | static void test_octchar(void) { | |
55 | assert_se(octchar(00) == '0'); | |
56 | assert_se(octchar(07) == '7'); | |
57 | } | |
58 | ||
59 | static void test_unoctchar(void) { | |
60 | assert_se(unoctchar('0') == 00); | |
61 | assert_se(unoctchar('7') == 07); | |
62 | } | |
63 | ||
64 | static void test_decchar(void) { | |
65 | assert_se(decchar(0) == '0'); | |
66 | assert_se(decchar(9) == '9'); | |
67 | } | |
68 | ||
69 | static void test_undecchar(void) { | |
70 | assert_se(undecchar('0') == 0); | |
71 | assert_se(undecchar('9') == 9); | |
72 | } | |
73 | ||
4937b81a YW |
74 | static void test_unhexmem_one(const char *s, size_t l, int retval) { |
75 | _cleanup_free_ char *hex = NULL; | |
13471436 RC |
76 | _cleanup_free_ void *mem = NULL; |
77 | size_t len; | |
78 | ||
4937b81a YW |
79 | assert_se(unhexmem(s, l, &mem, &len) == retval); |
80 | if (retval == 0) { | |
81 | char *answer; | |
82 | ||
dcd6361e | 83 | if (l == (size_t) -1) |
4937b81a YW |
84 | l = strlen(s); |
85 | ||
dcd6361e | 86 | assert_se(hex = hexmem(mem, len)); |
490c5a37 | 87 | answer = strndupa(strempty(s), l); |
4937b81a YW |
88 | assert_se(streq(delete_chars(answer, WHITESPACE), hex)); |
89 | } | |
90 | } | |
91 | ||
92 | static void test_unhexmem(void) { | |
93 | const char *hex = "efa2149213"; | |
94 | const char *hex_space = " e f a\n 2\r 14\n\r\t9\t2 \n1\r3 \r\r\t"; | |
95 | const char *hex_invalid = "efa214921o"; | |
13471436 | 96 | |
4937b81a YW |
97 | test_unhexmem_one(NULL, 0, 0); |
98 | test_unhexmem_one("", 0, 0); | |
99 | test_unhexmem_one("", (size_t) -1, 0); | |
100 | test_unhexmem_one(" \n \t\r \t\t \n\n\n", (size_t) -1, 0); | |
101 | test_unhexmem_one(hex_invalid, strlen(hex_invalid), -EINVAL); | |
102 | test_unhexmem_one(hex_invalid, (size_t) - 1, -EINVAL); | |
103 | test_unhexmem_one(hex, strlen(hex) - 1, -EPIPE); | |
104 | test_unhexmem_one(hex, strlen(hex), 0); | |
105 | test_unhexmem_one(hex, (size_t) -1, 0); | |
106 | test_unhexmem_one(hex_space, strlen(hex_space), 0); | |
107 | test_unhexmem_one(hex_space, (size_t) -1, 0); | |
13471436 RC |
108 | } |
109 | ||
110 | /* https://tools.ietf.org/html/rfc4648#section-10 */ | |
111 | static void test_base32hexmem(void) { | |
112 | char *b32; | |
113 | ||
fbd0b64f | 114 | b32 = base32hexmem("", STRLEN(""), true); |
13471436 RC |
115 | assert_se(b32); |
116 | assert_se(streq(b32, "")); | |
117 | free(b32); | |
118 | ||
fbd0b64f | 119 | b32 = base32hexmem("f", STRLEN("f"), true); |
13471436 RC |
120 | assert_se(b32); |
121 | assert_se(streq(b32, "CO======")); | |
122 | free(b32); | |
123 | ||
fbd0b64f | 124 | b32 = base32hexmem("fo", STRLEN("fo"), true); |
13471436 RC |
125 | assert_se(b32); |
126 | assert_se(streq(b32, "CPNG====")); | |
127 | free(b32); | |
128 | ||
fbd0b64f | 129 | b32 = base32hexmem("foo", STRLEN("foo"), true); |
13471436 RC |
130 | assert_se(b32); |
131 | assert_se(streq(b32, "CPNMU===")); | |
132 | free(b32); | |
133 | ||
fbd0b64f | 134 | b32 = base32hexmem("foob", STRLEN("foob"), true); |
13471436 RC |
135 | assert_se(b32); |
136 | assert_se(streq(b32, "CPNMUOG=")); | |
137 | free(b32); | |
138 | ||
fbd0b64f | 139 | b32 = base32hexmem("fooba", STRLEN("fooba"), true); |
13471436 RC |
140 | assert_se(b32); |
141 | assert_se(streq(b32, "CPNMUOJ1")); | |
142 | free(b32); | |
143 | ||
fbd0b64f | 144 | b32 = base32hexmem("foobar", STRLEN("foobar"), true); |
13471436 RC |
145 | assert_se(b32); |
146 | assert_se(streq(b32, "CPNMUOJ1E8======")); | |
147 | free(b32); | |
148 | ||
fbd0b64f | 149 | b32 = base32hexmem("", STRLEN(""), false); |
13471436 RC |
150 | assert_se(b32); |
151 | assert_se(streq(b32, "")); | |
152 | free(b32); | |
153 | ||
fbd0b64f | 154 | b32 = base32hexmem("f", STRLEN("f"), false); |
13471436 RC |
155 | assert_se(b32); |
156 | assert_se(streq(b32, "CO")); | |
157 | free(b32); | |
158 | ||
fbd0b64f | 159 | b32 = base32hexmem("fo", STRLEN("fo"), false); |
13471436 RC |
160 | assert_se(b32); |
161 | assert_se(streq(b32, "CPNG")); | |
162 | free(b32); | |
163 | ||
fbd0b64f | 164 | b32 = base32hexmem("foo", STRLEN("foo"), false); |
13471436 RC |
165 | assert_se(b32); |
166 | assert_se(streq(b32, "CPNMU")); | |
167 | free(b32); | |
168 | ||
fbd0b64f | 169 | b32 = base32hexmem("foob", STRLEN("foob"), false); |
13471436 RC |
170 | assert_se(b32); |
171 | assert_se(streq(b32, "CPNMUOG")); | |
172 | free(b32); | |
173 | ||
fbd0b64f | 174 | b32 = base32hexmem("fooba", STRLEN("fooba"), false); |
13471436 RC |
175 | assert_se(b32); |
176 | assert_se(streq(b32, "CPNMUOJ1")); | |
177 | free(b32); | |
178 | ||
fbd0b64f | 179 | b32 = base32hexmem("foobar", STRLEN("foobar"), false); |
13471436 RC |
180 | assert_se(b32); |
181 | assert_se(streq(b32, "CPNMUOJ1E8")); | |
182 | free(b32); | |
183 | } | |
184 | ||
2d2c21af YW |
185 | static void test_unbase32hexmem_one(const char *hex, bool padding, int retval, const char *ans) { |
186 | _cleanup_free_ void *mem = NULL; | |
13471436 RC |
187 | size_t len; |
188 | ||
2d2c21af YW |
189 | assert_se(unbase32hexmem(hex, (size_t) -1, padding, &mem, &len) == retval); |
190 | if (retval == 0) { | |
191 | char *str; | |
192 | ||
193 | str = strndupa(mem, len); | |
194 | assert_se(streq(str, ans)); | |
195 | } | |
196 | } | |
197 | ||
198 | static void test_unbase32hexmem(void) { | |
199 | test_unbase32hexmem_one("", true, 0, ""); | |
200 | ||
201 | test_unbase32hexmem_one("CO======", true, 0, "f"); | |
202 | test_unbase32hexmem_one("CPNG====", true, 0, "fo"); | |
203 | test_unbase32hexmem_one("CPNMU===", true, 0, "foo"); | |
204 | test_unbase32hexmem_one("CPNMUOG=", true, 0, "foob"); | |
205 | test_unbase32hexmem_one("CPNMUOJ1", true, 0, "fooba"); | |
206 | test_unbase32hexmem_one("CPNMUOJ1E8======", true, 0, "foobar"); | |
207 | ||
208 | test_unbase32hexmem_one("A", true, -EINVAL, NULL); | |
209 | test_unbase32hexmem_one("A=======", true, -EINVAL, NULL); | |
210 | test_unbase32hexmem_one("AAA=====", true, -EINVAL, NULL); | |
211 | test_unbase32hexmem_one("AAAAAA==", true, -EINVAL, NULL); | |
212 | test_unbase32hexmem_one("AB======", true, -EINVAL, NULL); | |
213 | test_unbase32hexmem_one("AAAB====", true, -EINVAL, NULL); | |
214 | test_unbase32hexmem_one("AAAAB===", true, -EINVAL, NULL); | |
215 | test_unbase32hexmem_one("AAAAAAB=", true, -EINVAL, NULL); | |
216 | ||
217 | test_unbase32hexmem_one("XPNMUOJ1", true, -EINVAL, NULL); | |
218 | test_unbase32hexmem_one("CXNMUOJ1", true, -EINVAL, NULL); | |
219 | test_unbase32hexmem_one("CPXMUOJ1", true, -EINVAL, NULL); | |
220 | test_unbase32hexmem_one("CPNXUOJ1", true, -EINVAL, NULL); | |
221 | test_unbase32hexmem_one("CPNMXOJ1", true, -EINVAL, NULL); | |
222 | test_unbase32hexmem_one("CPNMUXJ1", true, -EINVAL, NULL); | |
223 | test_unbase32hexmem_one("CPNMUOX1", true, -EINVAL, NULL); | |
224 | test_unbase32hexmem_one("CPNMUOJX", true, -EINVAL, NULL); | |
225 | ||
226 | test_unbase32hexmem_one("", false, 0, ""); | |
227 | test_unbase32hexmem_one("CO", false, 0, "f"); | |
228 | test_unbase32hexmem_one("CPNG", false, 0, "fo"); | |
229 | test_unbase32hexmem_one("CPNMU", false, 0, "foo"); | |
230 | test_unbase32hexmem_one("CPNMUOG", false, 0, "foob"); | |
231 | test_unbase32hexmem_one("CPNMUOJ1", false, 0, "fooba"); | |
232 | test_unbase32hexmem_one("CPNMUOJ1E8", false, 0, "foobar"); | |
233 | test_unbase32hexmem_one("CPNMUOG=", false, -EINVAL, NULL); | |
234 | test_unbase32hexmem_one("CPNMUOJ1E8======", false, -EINVAL, NULL); | |
235 | ||
2d2c21af YW |
236 | test_unbase32hexmem_one("A", false, -EINVAL, NULL); |
237 | test_unbase32hexmem_one("AAA", false, -EINVAL, NULL); | |
238 | test_unbase32hexmem_one("AAAAAA", false, -EINVAL, NULL); | |
239 | test_unbase32hexmem_one("AB", false, -EINVAL, NULL); | |
240 | test_unbase32hexmem_one("AAAB", false, -EINVAL, NULL); | |
241 | test_unbase32hexmem_one("AAAAB", false, -EINVAL, NULL); | |
242 | test_unbase32hexmem_one("AAAAAAB", false, -EINVAL, NULL); | |
13471436 RC |
243 | } |
244 | ||
245 | /* https://tools.ietf.org/html/rfc4648#section-10 */ | |
246 | static void test_base64mem(void) { | |
247 | char *b64; | |
248 | ||
fbd0b64f | 249 | assert_se(base64mem("", STRLEN(""), &b64) == 0); |
13471436 RC |
250 | assert_se(streq(b64, "")); |
251 | free(b64); | |
252 | ||
fbd0b64f | 253 | assert_se(base64mem("f", STRLEN("f"), &b64) == 4); |
13471436 RC |
254 | assert_se(streq(b64, "Zg==")); |
255 | free(b64); | |
256 | ||
fbd0b64f | 257 | assert_se(base64mem("fo", STRLEN("fo"), &b64) == 4); |
13471436 RC |
258 | assert_se(streq(b64, "Zm8=")); |
259 | free(b64); | |
260 | ||
fbd0b64f | 261 | assert_se(base64mem("foo", STRLEN("foo"), &b64) == 4); |
13471436 RC |
262 | assert_se(streq(b64, "Zm9v")); |
263 | free(b64); | |
264 | ||
fbd0b64f | 265 | assert_se(base64mem("foob", STRLEN("foob"), &b64) == 8); |
13471436 RC |
266 | assert_se(streq(b64, "Zm9vYg==")); |
267 | free(b64); | |
268 | ||
fbd0b64f | 269 | assert_se(base64mem("fooba", STRLEN("fooba"), &b64) == 8); |
13471436 RC |
270 | assert_se(streq(b64, "Zm9vYmE=")); |
271 | free(b64); | |
272 | ||
fbd0b64f | 273 | assert_se(base64mem("foobar", STRLEN("foobar"), &b64) == 8); |
13471436 RC |
274 | assert_se(streq(b64, "Zm9vYmFy")); |
275 | free(b64); | |
276 | } | |
277 | ||
081f36d8 LP |
278 | static void test_unbase64mem_one(const char *input, const char *output, int ret) { |
279 | _cleanup_free_ void *buffer = NULL; | |
280 | size_t size = 0; | |
13471436 | 281 | |
081f36d8 | 282 | assert_se(unbase64mem(input, (size_t) -1, &buffer, &size) == ret); |
13471436 | 283 | |
081f36d8 LP |
284 | if (ret >= 0) { |
285 | assert_se(size == strlen(output)); | |
286 | assert_se(memcmp(buffer, output, size) == 0); | |
287 | assert_se(((char*) buffer)[size] == 0); | |
288 | } | |
289 | } | |
13471436 | 290 | |
081f36d8 | 291 | static void test_unbase64mem(void) { |
13471436 | 292 | |
081f36d8 LP |
293 | test_unbase64mem_one("", "", 0); |
294 | test_unbase64mem_one("Zg==", "f", 0); | |
295 | test_unbase64mem_one("Zm8=", "fo", 0); | |
296 | test_unbase64mem_one("Zm9v", "foo", 0); | |
297 | test_unbase64mem_one("Zm9vYg==", "foob", 0); | |
298 | test_unbase64mem_one("Zm9vYmE=", "fooba", 0); | |
299 | test_unbase64mem_one("Zm9vYmFy", "foobar", 0); | |
300 | ||
301 | test_unbase64mem_one(" ", "", 0); | |
302 | test_unbase64mem_one(" \n\r ", "", 0); | |
303 | test_unbase64mem_one(" Zg\n== ", "f", 0); | |
304 | test_unbase64mem_one(" Zm 8=\r", "fo", 0); | |
305 | test_unbase64mem_one(" Zm9\n\r\r\nv ", "foo", 0); | |
306 | test_unbase64mem_one(" Z m9vYg==\n\r", "foob", 0); | |
307 | test_unbase64mem_one(" Zm 9vYmE= ", "fooba", 0); | |
308 | test_unbase64mem_one(" Z m9v YmFy ", "foobar", 0); | |
309 | ||
310 | test_unbase64mem_one("A", NULL, -EPIPE); | |
311 | test_unbase64mem_one("A====", NULL, -EINVAL); | |
312 | test_unbase64mem_one("AAB==", NULL, -EINVAL); | |
313 | test_unbase64mem_one(" A A A B = ", NULL, -EINVAL); | |
314 | test_unbase64mem_one(" Z m 8 = q u u x ", NULL, -ENAMETOOLONG); | |
13471436 RC |
315 | } |
316 | ||
317 | static void test_hexdump(void) { | |
318 | uint8_t data[146]; | |
319 | unsigned i; | |
320 | ||
321 | hexdump(stdout, NULL, 0); | |
322 | hexdump(stdout, "", 0); | |
323 | hexdump(stdout, "", 1); | |
324 | hexdump(stdout, "x", 1); | |
325 | hexdump(stdout, "x", 2); | |
326 | hexdump(stdout, "foobar", 7); | |
327 | hexdump(stdout, "f\nobar", 7); | |
328 | hexdump(stdout, "xxxxxxxxxxxxxxxxxxxxyz", 23); | |
329 | ||
330 | for (i = 0; i < ELEMENTSOF(data); i++) | |
331 | data[i] = i*2; | |
332 | ||
333 | hexdump(stdout, data, sizeof(data)); | |
334 | } | |
335 | ||
336 | int main(int argc, char *argv[]) { | |
337 | test_hexchar(); | |
338 | test_unhexchar(); | |
339 | test_base32hexchar(); | |
340 | test_unbase32hexchar(); | |
341 | test_base64char(); | |
342 | test_unbase64char(); | |
343 | test_octchar(); | |
344 | test_unoctchar(); | |
345 | test_decchar(); | |
346 | test_undecchar(); | |
347 | test_unhexmem(); | |
348 | test_base32hexmem(); | |
349 | test_unbase32hexmem(); | |
350 | test_base64mem(); | |
351 | test_unbase64mem(); | |
352 | test_hexdump(); | |
353 | ||
354 | return 0; | |
355 | } |