1 /*
2  * Wireshark - Network traffic analyzer
3  * By Gerald Combs <gerald@wireshark.org>
4  * Copyright 1998 Gerald Combs
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 #include "config.h"
10 
11 #include <stdio.h>
12 #include <glib.h>
13 #include <wsutil/utf8_entities.h>
14 
15 #include "str_util.h"
16 
17 
test_format_size(void)18 static void test_format_size(void)
19 {
20     char *str;
21 
22     str = format_size(10000, format_size_unit_bytes);
23     g_assert_cmpstr(str, ==, "10 kB");
24     g_free(str);
25 
26     str = format_size(100000, format_size_unit_bytes|format_size_prefix_iec);
27     g_assert_cmpstr(str, ==, "97 KiB");
28     g_free(str);
29 
30     str = format_size(20971520, format_size_unit_bits|format_size_prefix_iec);
31     g_assert_cmpstr(str, ==, "20 Mib");
32     g_free(str);
33 }
34 
35 #include "to_str.h"
36 
test_word_to_hex(void)37 static void test_word_to_hex(void)
38 {
39     static char buf[32];
40     char *str;     /* String is not NULL terminated. */
41 
42     str = guint8_to_hex(buf, 0x34);
43     g_assert_true(str == buf + 2);
44     g_assert_cmpint(str[-1], ==, '4');
45     g_assert_cmpint(str[-2], ==, '3');
46 
47     str = word_to_hex(buf, 0x1234);
48     g_assert_true(str == buf + 4);
49     g_assert_cmpint(str[-1], ==, '4');
50     g_assert_cmpint(str[-2], ==, '3');
51     g_assert_cmpint(str[-3], ==, '2');
52     g_assert_cmpint(str[-4], ==, '1');
53 
54     str = dword_to_hex(buf, 0x1234);
55     g_assert_true(str == buf + 8);
56     g_assert_cmpint(str[-1], ==, '4');
57     g_assert_cmpint(str[-2], ==, '3');
58     g_assert_cmpint(str[-3], ==, '2');
59     g_assert_cmpint(str[-4], ==, '1');
60     g_assert_cmpint(str[-5], ==, '0');
61     g_assert_cmpint(str[-6], ==, '0');
62     g_assert_cmpint(str[-7], ==, '0');
63     g_assert_cmpint(str[-8], ==, '0');
64 
65     str = qword_to_hex(buf, G_GUINT64_CONSTANT(0xFEDCBA987654321));
66     g_assert_true(str == buf + 16);
67     g_assert_cmpint(str[-1], ==, '1');
68     g_assert_cmpint(str[-2], ==, '2');
69     g_assert_cmpint(str[-3], ==, '3');
70     g_assert_cmpint(str[-4], ==, '4');
71     g_assert_cmpint(str[-5], ==, '5');
72     g_assert_cmpint(str[-6], ==, '6');
73     g_assert_cmpint(str[-7], ==, '7');
74     g_assert_cmpint(str[-8], ==, '8');
75     g_assert_cmpint(str[-9], ==, '9');
76     g_assert_cmpint(str[-10], ==, 'a');
77     g_assert_cmpint(str[-11], ==, 'b');
78     g_assert_cmpint(str[-12], ==, 'c');
79     g_assert_cmpint(str[-13], ==, 'd');
80     g_assert_cmpint(str[-14], ==, 'e');
81     g_assert_cmpint(str[-15], ==, 'f');
82     g_assert_cmpint(str[-16], ==, '0');
83 }
84 
test_bytes_to_str(void)85 static void test_bytes_to_str(void)
86 {
87     char *str;
88 
89     const guint8 buf[] = { 1, 2, 3};
90 
91     str = bytes_to_str(NULL, buf, sizeof(buf));
92     g_assert_cmpstr(str, ==, "010203");
93     g_free(str);
94 }
95 
test_bytes_to_str_punct(void)96 static void test_bytes_to_str_punct(void)
97 {
98     char *str;
99 
100     const guint8 buf[] = { 1, 2, 3};
101 
102     str = bytes_to_str_punct(NULL, buf, sizeof(buf), ':');
103     g_assert_cmpstr(str, ==, "01:02:03");
104     g_free(str);
105 }
106 
test_bytes_to_string_trunc1(void)107 static void test_bytes_to_string_trunc1(void)
108 {
109     char *str;
110 
111     const guint8 buf[] = {
112         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
113         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
114         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
115         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
116         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
117         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
118         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA
119     };
120     const char *expect =
121         "112233445566778899aa"
122         "112233445566778899aa"
123         "112233445566778899aa"
124         "112233445566" UTF8_HORIZONTAL_ELLIPSIS;
125 
126     str = bytes_to_str(NULL, buf, sizeof(buf));
127     g_assert_cmpstr(str, ==, expect);
128     g_free(str);
129 }
130 
test_bytes_to_string_punct_trunc1(void)131 static void test_bytes_to_string_punct_trunc1(void)
132 {
133     char *str;
134 
135     const guint8 buf[] = {
136         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
137         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
138         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
139         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
140         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
141         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
142         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA
143     };
144     const char *expect =
145         "11:22:33:44:55:66:77:88:99:aa:"
146         "11:22:33:44:55:66:77:88:99:aa:"
147         "11:22:33:44:" UTF8_HORIZONTAL_ELLIPSIS;
148 
149     str = bytes_to_str_punct(NULL, buf, sizeof(buf), ':');
150     g_assert_cmpstr(str, ==, expect);
151     g_free(str);
152 }
153 
154 static char to_str_back_buf[32];
155 #define BACK_PTR (&to_str_back_buf[31]) /* pointer to NUL string terminator */
156 
test_oct_to_str_back(void)157 static void test_oct_to_str_back(void)
158 {
159     char *str;
160 
161     str = oct_to_str_back(BACK_PTR, 958769886);
162     g_assert_cmpstr(str,  ==, "07111325336");
163 
164     str = oct_to_str_back(BACK_PTR, 781499127);
165     g_assert_cmpstr(str,  ==, "05645135367");
166 
167     str = oct_to_str_back(BACK_PTR, 1177329882);
168     g_assert_cmpstr(str, ==, "010613120332");
169 }
170 
test_oct64_to_str_back(void)171 static void test_oct64_to_str_back(void)
172 {
173     char *str;
174 
175     str = oct64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(13873797580070999420));
176     g_assert_cmpstr(str, ==, "01402115026217563452574");
177 
178     str = oct64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(7072159458371400691));
179     g_assert_cmpstr(str, ==, "0610452670726711271763");
180 
181     str = oct64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(12453513102400590374));
182     g_assert_cmpstr(str, ==, "01263236102754220511046");
183 }
184 
test_hex_to_str_back_len(void)185 static void test_hex_to_str_back_len(void)
186 {
187     char *str;
188 
189     str = hex_to_str_back_len(BACK_PTR, 2481, 8);
190     g_assert_cmpstr(str, ==, "0x000009b1");
191 
192     str = hex_to_str_back_len(BACK_PTR, 2457, 8);
193     g_assert_cmpstr(str, ==, "0x00000999");
194 
195     str = hex_to_str_back_len(BACK_PTR, 16230, 8);
196     g_assert_cmpstr(str, ==, "0x00003f66");
197 }
198 
test_hex64_to_str_back_len(void)199 static void test_hex64_to_str_back_len(void)
200 {
201     char *str;
202 
203     str = hex64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(1), 16);
204     g_assert_cmpstr(str, ==, "0x0000000000000001");
205 
206     str = hex64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(4294967295), 16);
207     g_assert_cmpstr(str, ==, "0x00000000ffffffff");
208 
209     str = hex64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(18446744073709551615), 16);
210     g_assert_cmpstr(str, ==, "0xffffffffffffffff");
211 }
212 
test_uint_to_str_back(void)213 static void test_uint_to_str_back(void)
214 {
215     char *str;
216 
217     str = uint_to_str_back(BACK_PTR, 873735883);
218     g_assert_cmpstr(str, ==, "873735883");
219 
220     str = uint_to_str_back(BACK_PTR, 1801148094);
221     g_assert_cmpstr(str, ==, "1801148094");
222 
223     str = uint_to_str_back(BACK_PTR, 181787997);
224     g_assert_cmpstr(str, ==, "181787997");
225 }
226 
test_uint64_to_str_back(void)227 static void test_uint64_to_str_back(void)
228 {
229     char *str;
230 
231     str = uint64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(585143757104211265));
232     g_assert_cmpstr(str, ==, "585143757104211265");
233 
234     str = uint64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(7191580247919484847));
235     g_assert_cmpstr(str, ==, "7191580247919484847");
236 
237     str = uint64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(95778573911934485));
238     g_assert_cmpstr(str, ==, "95778573911934485");
239 }
240 
test_uint_to_str_back_len(void)241 static void test_uint_to_str_back_len(void)
242 {
243     char *str;
244 
245     str = uint_to_str_back_len(BACK_PTR, 26630, 8);
246     g_assert_cmpstr(str, ==, "00026630");
247 
248     str = uint_to_str_back_len(BACK_PTR, 25313, 8);
249     g_assert_cmpstr(str, ==, "00025313");
250 
251     str = uint_to_str_back_len(BACK_PTR, 18750000, 8);
252     g_assert_cmpstr(str, ==, "18750000");
253 }
254 
test_uint64_to_str_back_len(void)255 static void test_uint64_to_str_back_len(void)
256 {
257     char *str;
258 
259     str = uint64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(1), 16);
260     g_assert_cmpstr(str, ==, "0000000000000001");
261 
262     str = uint64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(4294967295), 16);
263     g_assert_cmpstr(str, ==, "0000004294967295");
264 
265     str = uint64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(18446744073709551615), 16);
266     g_assert_cmpstr(str, ==, "18446744073709551615");
267 }
268 
test_int_to_str_back(void)269 static void test_int_to_str_back(void)
270 {
271     char *str;
272 
273     str = int_to_str_back(BACK_PTR, -763689611);
274     g_assert_cmpstr(str, ==, "-763689611");
275 
276     str = int_to_str_back(BACK_PTR, -296015954);
277     g_assert_cmpstr(str, ==, "-296015954");
278 
279     str = int_to_str_back(BACK_PTR, 898901469);
280     g_assert_cmpstr(str, ==, "898901469");
281 }
282 
test_int64_to_str_back(void)283 static void test_int64_to_str_back(void)
284 {
285     char *str;
286 
287     str = int64_to_str_back(BACK_PTR, G_GINT64_CONSTANT(-9223372036854775807));
288     g_assert_cmpstr(str, ==, "-9223372036854775807");
289 
290     str = int64_to_str_back(BACK_PTR, G_GINT64_CONSTANT(1));
291     g_assert_cmpstr(str, ==, "1");
292 
293     str = int64_to_str_back(BACK_PTR, G_GINT64_CONSTANT(9223372036854775807));
294     g_assert_cmpstr(str, ==, "9223372036854775807");
295 }
296 
297 #include "ws_getopt.h"
298 
299 #define ARGV_MAX 31
300 
new_argv(int * argc_ptr,const char * args,...)301 static char **new_argv(int *argc_ptr, const char *args, ...)
302 {
303     char **argv;
304     int argc = 0;
305     va_list ap;
306 
307     argv = g_malloc((ARGV_MAX + 1) * sizeof(char *));
308 
309     va_start(ap, args);
310     while (args != NULL) {
311         /* Increase ARGV_MAX or use a dynamic size if this assertion fails. */
312         g_assert_true(argc < ARGV_MAX);
313         argv[argc++] = g_strdup(args);
314         args = va_arg(ap, const char *);
315     }
316     argv[argc] = NULL;
317     va_end(ap);
318 
319     *argc_ptr = argc;
320     return argv;
321 }
322 
free_argv(char ** argv)323 static void free_argv(char **argv)
324 {
325     for (char **p = argv; *p != NULL; p++) {
326         g_free(*p);
327     }
328     g_free(argv);
329 }
330 
test_getopt_long_basic1(void)331 static void test_getopt_long_basic1(void)
332 {
333     char **argv;
334     int argc;
335 
336     const char *optstring = "ab:c";
337     argv = new_argv(&argc, "/bin/ls", "-a", "-b", "arg1", "-c", "path", (char *)NULL);
338 
339     ws_optind = 1;
340     int opt;
341 
342     opt = ws_getopt_long(argc, argv, optstring, NULL, NULL);
343     g_assert_cmpint(opt, ==, 'a');
344     g_assert_null(ws_optarg);
345 
346     opt = ws_getopt_long(argc, argv, optstring, NULL, NULL);
347     g_assert_cmpint(opt, ==, 'b');
348     g_assert_cmpstr(ws_optarg, ==, "arg1");
349 
350     opt = ws_getopt_long(argc, argv, optstring, NULL, NULL);
351     g_assert_cmpint(opt, ==, 'c');
352     g_assert_null(ws_optarg);
353 
354     opt = ws_getopt_long(argc, argv, optstring, NULL, NULL);
355     g_assert_cmpint(opt, ==, -1);
356 
357     free_argv(argv);
358 }
359 
test_getopt_long_basic2(void)360 static void test_getopt_long_basic2(void)
361 {
362     char **argv;
363     int argc;
364 
365     struct ws_option longopts[] = {
366         { "opt1", ws_no_argument, NULL, '1' },
367         { "opt2", ws_required_argument, NULL, '2' },
368         { "opt3", ws_required_argument, NULL, '3' },
369         { 0, 0, 0, 0 }
370     };
371     argv = new_argv(&argc, "/bin/ls", "--opt1", "--opt2", "arg1", "--opt3=arg2", "path", (char *)NULL);
372 
373     ws_optind = 1;
374     int opt;
375 
376     opt = ws_getopt_long(argc, argv, "", longopts, NULL);
377     g_assert_cmpint(opt, ==, '1');
378     g_assert_null(ws_optarg);
379 
380     opt = ws_getopt_long(argc, argv, "", longopts, NULL);
381     g_assert_cmpint(opt, ==, '2');
382     g_assert_cmpstr(ws_optarg, ==, "arg1");
383 
384     opt = ws_getopt_long(argc, argv, "", longopts, NULL);
385     g_assert_cmpint(opt, ==, '3');
386     g_assert_cmpstr(ws_optarg, ==, "arg2");
387 
388     opt = ws_getopt_long(argc, argv, "", longopts, NULL);
389     g_assert_cmpint(opt, ==, -1);
390 
391     free_argv(argv);
392 }
393 
test_getopt_optional_argument1(void)394 static void test_getopt_optional_argument1(void)
395 {
396     char **argv;
397     int argc;
398     int opt;
399 
400     struct ws_option longopts_optional[] = {
401         { "optional", ws_optional_argument, NULL, '1' },
402         { 0, 0, 0, 0 }
403     };
404 
405     argv = new_argv(&argc, "/bin/ls", "--optional=arg1", (char *)NULL);
406 
407     ws_optreset = 1;
408     opt = ws_getopt_long(argc, argv, "", longopts_optional, NULL);
409     g_assert_cmpint(opt, ==, '1');
410     g_assert_cmpstr(ws_optarg, ==, "arg1");
411 
412     free_argv(argv);
413     argv = new_argv(&argc, "/bin/ls", "--optional", "arg1", (char *)NULL);
414 
415     ws_optreset = 1;
416     opt = ws_getopt_long(argc, argv, "", longopts_optional, NULL);
417     g_assert_cmpint(opt, ==, '1');
418     /* Optional argument does not recognize the form "--arg param" (it's ambiguous). */
419     g_assert_null(ws_optarg);
420 
421     free_argv(argv);
422     argv = new_argv(&argc, "/bin/ls", "--optional", (char *)NULL);
423 
424     ws_optreset = 1;
425     opt = ws_getopt_long(argc, argv, "", longopts_optional, NULL);
426     g_assert_cmpint(opt, ==, '1');
427     g_assert_null(ws_optarg);
428 
429     free_argv(argv);
430 }
431 
test_getopt_opterr1(void)432 static void test_getopt_opterr1(void)
433 {
434     char **argv;
435     int argc;
436 
437 #ifdef _WIN32
438     g_test_skip("Not supported on Windows");
439     return;
440 #endif
441 
442     if (g_test_subprocess()) {
443         const char *optstring = "ab";
444         argv = new_argv(&argc, "/bin/ls", "-a", "-z", "path", (char *)NULL);
445 
446         ws_optind = 0;
447         ws_opterr = 1;
448         int opt;
449 
450         opt = ws_getopt_long(argc, argv, optstring, NULL, NULL);
451         g_assert_cmpint(opt, ==, 'a');
452 
453         opt = ws_getopt_long(argc, argv, optstring, NULL, NULL);
454         g_assert_cmpint(opt, ==, '?');
455         g_assert_cmpint(ws_optopt, ==, 'z');
456 
457         opt = ws_getopt_long(argc, argv, optstring, NULL, NULL);
458         g_assert_cmpint(opt, ==, -1);
459 
460         free_argv(argv);
461 
462         return;
463     }
464 
465     g_test_trap_subprocess(NULL, 0, 0);
466     g_test_trap_assert_passed();
467     g_test_trap_assert_stderr("/bin/ls: unrecognized option: z\n");
468 }
469 
main(int argc,char ** argv)470 int main(int argc, char **argv)
471 {
472     int ret;
473 
474     g_test_init(&argc, &argv, NULL);
475 
476     g_test_add_func("/str_util/format_size", test_format_size);
477 
478     g_test_add_func("/to_str/word_to_hex", test_word_to_hex);
479     g_test_add_func("/to_str/bytes_to_str", test_bytes_to_str);
480     g_test_add_func("/to_str/bytes_to_str_punct", test_bytes_to_str_punct);
481     g_test_add_func("/to_str/bytes_to_str_trunc1", test_bytes_to_string_trunc1);
482     g_test_add_func("/to_str/bytes_to_str_punct_trunc1", test_bytes_to_string_punct_trunc1);
483     g_test_add_func("/to_str/oct_to_str_back", test_oct_to_str_back);
484     g_test_add_func("/to_str/oct64_to_str_back", test_oct64_to_str_back);
485     g_test_add_func("/to_str/hex_to_str_back_len", test_hex_to_str_back_len);
486     g_test_add_func("/to_str/hex64_to_str_back_len", test_hex64_to_str_back_len);
487     g_test_add_func("/to_str/uint_to_str_back", test_uint_to_str_back);
488     g_test_add_func("/to_str/uint64_to_str_back", test_uint64_to_str_back);
489     g_test_add_func("/to_str/uint_to_str_back_len", test_uint_to_str_back_len);
490     g_test_add_func("/to_str/uint64_to_str_back_len", test_uint64_to_str_back_len);
491     g_test_add_func("/to_str/int_to_str_back", test_int_to_str_back);
492     g_test_add_func("/to_str/int64_to_str_back", test_int64_to_str_back);
493 
494     g_test_add_func("/ws_getopt/basic1", test_getopt_long_basic1);
495     g_test_add_func("/ws_getopt/basic2", test_getopt_long_basic2);
496     g_test_add_func("/ws_getopt/optional1", test_getopt_optional_argument1);
497     g_test_add_func("/ws_getopt/opterr1", test_getopt_opterr1);
498 
499     ret = g_test_run();
500 
501     return ret;
502 }
503 
504 /*
505  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
506  *
507  * Local variables:
508  * c-basic-offset: 4
509  * tab-width: 8
510  * indent-tabs-mode: nil
511  * End:
512  *
513  * vi: set shiftwidth=4 tabstop=8 expandtab:
514  * :indentSize=4:tabSize=8:noTabs=true:
515  */
516