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