Line data Source code
1 : /*
2 : * Tests for strv_util
3 : *
4 : * Copyright Martin Schwenke <martin@meltin.net> 2016
5 : * Copyright Christof Schmitt <cs@samba.org> 2018
6 : * Copyright Swen Schillig <swen@linux.ibm.com> 2019
7 : *
8 : * This program is free software; you can redistribute it and/or modify
9 : * it under the terms of the GNU General Public License as published by
10 : * the Free Software Foundation; either version 3 of the License, or
11 : * (at your option) any later version.
12 : *
13 : * This program is distributed in the hope that it will be useful,
14 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : * GNU General Public License for more details.
17 : *
18 : * You should have received a copy of the GNU General Public License
19 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include <talloc.h>
23 :
24 : #include "replace.h"
25 : #include "system/filesys.h"
26 :
27 : #include "libcli/util/ntstatus.h"
28 : #include "torture/torture.h"
29 : #include "lib/util/data_blob.h"
30 : #include "torture/local/proto.h"
31 :
32 : #include "lib/util/samba_util.h"
33 : #include "lib/util/smb_strtox.h"
34 :
35 : #include "limits.h"
36 : #include "string.h"
37 :
38 : struct test_trim_string_data {
39 : const char *desc;
40 : const char *in;
41 : const char *front;
42 : const char *back;
43 : const char *out;
44 : bool ret;
45 : };
46 :
47 : static const struct test_trim_string_data test_trim_string_data[] = {
48 : {
49 : .desc = "All NULL",
50 : .in = NULL,
51 : .front = NULL,
52 : .back = NULL,
53 : .out = NULL,
54 : .ret = false,
55 : },
56 : {
57 : .desc = "Input NULL",
58 : .in = NULL,
59 : .front = "abc",
60 : .back = "123",
61 : .out = NULL,
62 : .ret = false,
63 : },
64 : {
65 : .desc = "Trim NULL",
66 : .in = "abc",
67 : .front = NULL,
68 : .back = NULL,
69 : .out = "abc",
70 : .ret = false,
71 : },
72 : {
73 : .desc = "Trim empty",
74 : .in = "abc",
75 : .front = "",
76 : .back = "",
77 : .out = "abc",
78 : .ret = false,
79 : },
80 : {
81 : .desc = "Trim front, non-matching",
82 : .in = "abc",
83 : .front = "x",
84 : .back = "",
85 : .out = "abc",
86 : .ret = false,
87 : },
88 : {
89 : .desc = "Trim front, matches back",
90 : .in = "abc",
91 : .front = "c",
92 : .back = "",
93 : .out = "abc",
94 : .ret = false,
95 : },
96 : {
97 : .desc = "Trim front, partial-match",
98 : .in = "abc",
99 : .front = "ac",
100 : .back = "",
101 : .out = "abc",
102 : .ret = false,
103 : },
104 : {
105 : .desc = "Trim front, too long",
106 : .in = "aaa",
107 : .front = "aaaa",
108 : .back = "",
109 : .out = "aaa",
110 : .ret = false,
111 : },
112 : {
113 : .desc = "Trim front, 1 char, 1x",
114 : .in = "abc",
115 : .front = "a",
116 : .back = "",
117 : .out = "bc",
118 : .ret = true,
119 : },
120 : {
121 : .desc = "Trim front, 1 char, 2x",
122 : .in = "aabc",
123 : .front = "a",
124 : .back = "",
125 : .out = "bc",
126 : .ret = true,
127 : },
128 : {
129 : .desc = "Trim front, 1 char, 3x",
130 : .in = "aaabc",
131 : .front = "a",
132 : .back = "",
133 : .out = "bc",
134 : .ret = true,
135 : },
136 : {
137 : .desc = "Trim front, 1 char, matches all",
138 : .in = "aaa",
139 : .front = "a",
140 : .back = "",
141 : .out = "",
142 : .ret = true,
143 : },
144 : {
145 : .desc = "Trim front, 2 chars, 1x",
146 : .in = "abc",
147 : .front = "ab",
148 : .back = "",
149 : .out = "c",
150 : .ret = true,
151 : },
152 : {
153 : .desc = "Trim front, 2 chars, 2x",
154 : .in = "ababc",
155 : .front = "ab",
156 : .back = "",
157 : .out = "c",
158 : .ret = true,
159 : },
160 : {
161 : .desc = "Trim front, 3 chars, matches all",
162 : .in = "abc",
163 : .front = "abc",
164 : .back = "",
165 : .out = "",
166 : .ret = true,
167 : },
168 : {
169 : .desc = "Trim back, non-matching",
170 : .in = "abc",
171 : .front = "",
172 : .back = "x",
173 : .out = "abc",
174 : .ret = false,
175 : },
176 : {
177 : .desc = "Trim back, matches front",
178 : .in = "abc",
179 : .front = "",
180 : .back = "a",
181 : .out = "abc",
182 : .ret = false,
183 : },
184 : {
185 : .desc = "Trim back, partial-match",
186 : .in = "abc",
187 : .front = "",
188 : .back = "xc",
189 : .out = "abc",
190 : .ret = false,
191 : },
192 : {
193 : .desc = "Trim back, too long",
194 : .in = "aaa",
195 : .front = "",
196 : .back = "aaaa",
197 : .out = "aaa",
198 : .ret = false,
199 : },
200 : {
201 : .desc = "Trim back, 1 char, 1x",
202 : .in = "abc",
203 : .front = "",
204 : .back = "c",
205 : .out = "ab",
206 : .ret = true,
207 : },
208 : {
209 : .desc = "Trim back, 1 char, 2x",
210 : .in = "abcc",
211 : .front = "",
212 : .back = "c",
213 : .out = "ab",
214 : .ret = true,
215 : },
216 : {
217 : .desc = "Trim back, 1 char, 3x",
218 : .in = "abccc",
219 : .front = "",
220 : .back = "c",
221 : .out = "ab",
222 : .ret = true,
223 : },
224 : {
225 : .desc = "Trim back, 1 char, matches all",
226 : .in = "aaa",
227 : .front = "",
228 : .back = "a",
229 : .out = "",
230 : .ret = true,
231 : },
232 : {
233 : .desc = "Trim back, 2 chars, 1x",
234 : .in = "abc",
235 : .front = "",
236 : .back = "bc",
237 : .out = "a",
238 : .ret = true,
239 : },
240 : {
241 : .desc = "Trim back, 2 chars, 2x",
242 : .in = "abcbc",
243 : .front = "",
244 : .back = "bc",
245 : .out = "a",
246 : .ret = true,
247 : },
248 : {
249 : .desc = "Trim back, 3 chars, matches all",
250 : .in = "abc",
251 : .front = "",
252 : .back = "abc",
253 : .out = "",
254 : .ret = true,
255 : },
256 : {
257 : .desc = "Trim both, non-matching",
258 : .in = "abc",
259 : .front = "x",
260 : .back = "y",
261 : .out = "abc",
262 : .ret = false,
263 : },
264 : {
265 : .desc = "Trim both, reversed",
266 : .in = "abc",
267 : .front = "c",
268 : .back = "a",
269 : .out = "abc",
270 : .ret = false,
271 : },
272 : {
273 : .desc = "Trim both, 1 char, 1x",
274 : .in = "abc",
275 : .front = "a",
276 : .back = "c",
277 : .out = "b",
278 : .ret = true,
279 : },
280 : {
281 : .desc = "Trim both, 1 char, 2x",
282 : .in = "aabcc",
283 : .front = "a",
284 : .back = "c",
285 : .out = "b",
286 : .ret = true,
287 : },
288 : {
289 : .desc = "Trim both, 1 char, 3x",
290 : .in = "aaabccc",
291 : .front = "a",
292 : .back = "c",
293 : .out = "b",
294 : .ret = true,
295 : },
296 : {
297 : .desc = "Trim both, 1 char, matches all",
298 : .in = "aaabbb",
299 : .front = "a",
300 : .back = "b",
301 : .out = "",
302 : .ret = true,
303 : },
304 : {
305 : .desc = "Trim both, 2 chars, 1x",
306 : .in = "abxbc",
307 : .front = "ab",
308 : .back = "bc",
309 : .out = "x",
310 : .ret = true,
311 : },
312 : {
313 : .desc = "Trim both, 2 chars, 2x",
314 : .in = "ababxyzbcbc",
315 : .front = "ab",
316 : .back = "bc",
317 : .out = "xyz",
318 : .ret = true,
319 : },
320 : {
321 : .desc = "Trim both, 2 chars, front matches, back doesn't",
322 : .in = "abcde",
323 : .front = "ab",
324 : .back = "xy",
325 : .out = "cde",
326 : .ret = true,
327 : },
328 : {
329 : .desc = "Trim both, 2 chars, back matches, front doesn't",
330 : .in = "abcde",
331 : .front = "xy",
332 : .back = "de",
333 : .out = "abc",
334 : .ret = true,
335 : },
336 : {
337 : .desc = "Trim back, 3 chars, matches all",
338 : .in = "abcxyz",
339 : .front = "abc",
340 : .back = "xyz",
341 : .out = "",
342 : .ret = true,
343 : },
344 : };
345 :
346 0 : static bool test_trim_string(struct torture_context *tctx)
347 : {
348 : int j;
349 0 : for (j = 0; j < ARRAY_SIZE(test_trim_string_data); j++) {
350 : bool ret;
351 0 : const struct test_trim_string_data *d =
352 : &test_trim_string_data[j];
353 0 : char *str = talloc_strdup(tctx, d->in);
354 0 : torture_assert(tctx, d->in == NULL || str != NULL,
355 : "Out of memory");
356 :
357 0 : torture_comment(tctx, "%s\n", d->desc);
358 0 : ret = trim_string(str, d->front, d->back);
359 0 : torture_assert(tctx, ret == d->ret,
360 : "Incorrect return from trim_string()");
361 0 : if (d->out == NULL) {
362 0 : torture_assert(tctx, str == NULL, "Expected NULL");
363 : } else {
364 0 : torture_assert(tctx, str != NULL, "Expected non-NULL");
365 0 : torture_assert_str_equal(tctx, str, d->out,
366 : "Incorrect output");
367 : }
368 0 : TALLOC_FREE(str);
369 : }
370 :
371 0 : return true;
372 : }
373 :
374 0 : static bool test_directory_create_or_exist(struct torture_context *tctx)
375 : {
376 0 : char *path = NULL, *new_path = NULL, *file_path = NULL;
377 0 : bool ret = true, b = true;
378 : int fd;
379 : NTSTATUS status;
380 0 : const mode_t perms = 0741;
381 :
382 0 : status = torture_temp_dir(tctx, "util_dir", &path);;
383 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
384 : "Creating test directory failed.\n");
385 :
386 0 : b = directory_create_or_exist(path, perms);
387 0 : torture_assert_goto(tctx, b == true, ret, done,
388 : "directory_create_or_exist on "
389 : "existing directory failed.\n");
390 :
391 0 : new_path = talloc_asprintf(tctx, "%s/%s", path, "dir");
392 0 : torture_assert_goto(tctx, new_path != NULL, ret, done,
393 : "Could not allocate memory for directory path\n");
394 :
395 0 : b = directory_exist(new_path);
396 0 : torture_assert_goto(tctx, b == false, ret, done,
397 : "Check for non-existing directory failed.\n");
398 :
399 0 : b = directory_create_or_exist(new_path, perms);
400 0 : torture_assert_goto(tctx, b == true, ret, done,
401 : "directory_create_or_exist for "
402 : "new directory failed.\n");
403 :
404 0 : b = directory_exist(new_path);
405 0 : torture_assert_goto(tctx, b == true, ret, done,
406 : "Check for existing directory failed.\n");
407 :
408 0 : b = file_check_permissions(new_path, geteuid(), perms, NULL);
409 0 : torture_assert_goto(tctx, b == true, ret, done,
410 : "Permission check for directory failed.\n");
411 :
412 0 : file_path = talloc_asprintf(tctx, "%s/%s", path, "file");
413 0 : torture_assert_goto(tctx, file_path != NULL, ret, done,
414 : "Could not allocate memory for file path\n");
415 0 : fd = creat(file_path, perms);
416 0 : torture_assert_goto(tctx, fd != -1, ret, done,
417 : "Creating file failed.\n");
418 0 : close(fd);
419 :
420 0 : b = directory_create_or_exist(file_path, perms);
421 0 : torture_assert_goto(tctx, b == false, ret, done,
422 : "directory_create_or_exist for "
423 : "existing file failed.\n");
424 :
425 0 : done:
426 0 : return ret;
427 : }
428 :
429 0 : static bool test_mem_equal_const_time(struct torture_context *tctx)
430 : {
431 0 : const char *test_string = "abcdabcd";
432 :
433 0 : torture_assert(tctx, mem_equal_const_time("", "", 0),
434 : "zero-length comparison failed");
435 :
436 0 : torture_assert(tctx, mem_equal_const_time(test_string, test_string, 8),
437 : "comparison with equal pointers failed");
438 :
439 0 : torture_assert(tctx, mem_equal_const_time(test_string, test_string + 4, 4),
440 : "comparison with non-equal pointers failed");
441 :
442 0 : torture_assert(tctx, !mem_equal_const_time("abcd", "efgh", 4),
443 : "comparison with different values failed");
444 :
445 0 : return true;
446 : }
447 :
448 0 : static bool test_smb_strtoul_errno_check(struct torture_context *tctx)
449 : {
450 0 : const char *number = "123";
451 0 : unsigned long int val = 0;
452 0 : unsigned long long int vall = 0;
453 : int err;
454 :
455 : /* select an error code which is not set by the smb_strtoul routines */
456 0 : errno = EAGAIN;
457 0 : err = EAGAIN;
458 0 : val = smb_strtoul(number, NULL, 0, &err, SMB_STR_STANDARD);
459 0 : torture_assert(tctx, errno == EAGAIN, "smb_strtoul: Expected EAGAIN");
460 0 : torture_assert(tctx, err == 0, "smb_strtoul: Expected err = 0");
461 0 : torture_assert(tctx, val == 123, "smb_strtoul: Expected value 123");
462 :
463 : /* set err to an impossible value again before continuing */
464 0 : err = EAGAIN;
465 0 : vall = smb_strtoull(number, NULL, 0, &err, SMB_STR_STANDARD);
466 0 : torture_assert(tctx, errno == EAGAIN, "smb_strtoull: Expected EAGAIN");
467 0 : torture_assert(tctx, err == 0, "smb_strtoul: Expected err = 0");
468 0 : torture_assert(tctx, vall == 123, "smb_strtoul: Expected value 123");
469 :
470 0 : return true;
471 : }
472 :
473 0 : static bool test_smb_strtoul_negative(struct torture_context *tctx)
474 : {
475 0 : const char *number = "-132";
476 0 : const char *number2 = "132-";
477 0 : unsigned long int val = 0;
478 0 : unsigned long long int vall = 0;
479 : int err;
480 :
481 0 : err = 0;
482 0 : smb_strtoul(number, NULL, 0, &err, SMB_STR_STANDARD);
483 0 : torture_assert(tctx, err == EINVAL, "smb_strtoul: Expected EINVAL");
484 :
485 0 : err = 0;
486 0 : smb_strtoull(number, NULL, 0, &err, SMB_STR_STANDARD);
487 0 : torture_assert(tctx, err == EINVAL, "smb_strtoull: Expected EINVAL");
488 :
489 : /* it is allowed to have a "-" sign after a number,
490 : * e.g. as part of a formular, however, it is not supposed to
491 : * have an effect on the converted value.
492 : */
493 :
494 0 : err = 0;
495 0 : val = smb_strtoul(number2, NULL, 0, &err, SMB_STR_STANDARD);
496 0 : torture_assert(tctx, err == 0, "smb_strtoul: Expected no error");
497 0 : torture_assert(tctx, val == 132, "smb_strtoul: Wrong value");
498 :
499 0 : err = 0;
500 0 : vall = smb_strtoull(number2, NULL, 0, &err, SMB_STR_STANDARD);
501 0 : torture_assert(tctx, err == 0, "smb_strtoull: Expected no error");
502 0 : torture_assert(tctx, vall == 132, "smb_strtoull: Wrong value");
503 :
504 0 : return true;
505 : }
506 :
507 0 : static bool test_smb_strtoul_no_number(struct torture_context *tctx)
508 : {
509 0 : const char *number = "ghijk";
510 0 : const char *blank = "";
511 : int err;
512 :
513 0 : err = 0;
514 0 : smb_strtoul(number, NULL, 0, &err, SMB_STR_STANDARD);
515 0 : torture_assert(tctx, err == EINVAL, "smb_strtoul: Expected EINVAL");
516 :
517 0 : err = 0;
518 0 : smb_strtoull(number, NULL, 0, &err, SMB_STR_STANDARD);
519 0 : torture_assert(tctx, err == EINVAL, "smb_strtoull: Expected EINVAL");
520 :
521 0 : err = 0;
522 0 : smb_strtoul(blank, NULL, 0, &err, SMB_STR_STANDARD);
523 0 : torture_assert(tctx, err == EINVAL, "smb_strtoul: Expected EINVAL");
524 :
525 0 : err = 0;
526 0 : smb_strtoull(blank, NULL, 0, &err, SMB_STR_STANDARD);
527 0 : torture_assert(tctx, err == EINVAL, "smb_strtoull: Expected EINVAL");
528 :
529 0 : return true;
530 : }
531 :
532 0 : static bool test_smb_strtoul_allow_negative(struct torture_context *tctx)
533 : {
534 0 : const char *number = "-1";
535 0 : const char *number2 = "-1-1";
536 0 : unsigned long res = 0;
537 0 : unsigned long long res2 = 0;
538 0 : char *end_ptr = NULL;
539 : int err;
540 :
541 0 : err = 0;
542 0 : res = smb_strtoul(number, NULL, 0, &err, SMB_STR_ALLOW_NEGATIVE);
543 0 : torture_assert(tctx, err == 0, "strtoul_err: Unexpected error");
544 0 : torture_assert(tctx, res == ULONG_MAX, "strtoul_err: Unexpected value");
545 :
546 0 : err = 0;
547 0 : res2 = smb_strtoull(number, NULL, 0, &err, SMB_STR_ALLOW_NEGATIVE);
548 0 : torture_assert(tctx, err == 0, "strtoull_err: Unexpected error");
549 0 : torture_assert(tctx, res2 == ULLONG_MAX, "strtoull_err: Unexpected value");
550 :
551 0 : err = 0;
552 0 : smb_strtoul(number2, &end_ptr, 0, &err, SMB_STR_ALLOW_NEGATIVE);
553 0 : torture_assert(tctx, err == 0, "strtoul_err: Unexpected error");
554 0 : torture_assert(tctx, end_ptr[0] == '-', "strtoul_err: Unexpected end pointer");
555 :
556 0 : err = 0;
557 0 : smb_strtoull(number2, &end_ptr, 0, &err, SMB_STR_ALLOW_NEGATIVE);
558 0 : torture_assert(tctx, err == 0, "strtoull_err: Unexpected error");
559 0 : torture_assert(tctx, end_ptr[0] == '-', "strtoull_err: Unexpected end pointer");
560 :
561 0 : return true;
562 : }
563 :
564 0 : static bool test_smb_strtoul_full_string(struct torture_context *tctx)
565 : {
566 0 : const char *number = "123 ";
567 0 : const char *number2 = "123";
568 : int err;
569 :
570 0 : err = 0;
571 0 : smb_strtoul(number, NULL, 0, &err, SMB_STR_FULL_STR_CONV);
572 0 : torture_assert(tctx, err == EINVAL, "strtoul_err: Expected EINVAL");
573 :
574 0 : err = 0;
575 0 : smb_strtoull(number, NULL, 0, &err, SMB_STR_FULL_STR_CONV);
576 0 : torture_assert(tctx, err == EINVAL, "strtoull_err: Expected EINVAL");
577 :
578 0 : err = 0;
579 0 : smb_strtoul(number2, NULL, 0, &err, SMB_STR_FULL_STR_CONV);
580 0 : torture_assert(tctx, err == 0, "strtoul_err: Unexpected error");
581 :
582 0 : err = 0;
583 0 : smb_strtoull(number2, NULL, 0, &err, SMB_STR_FULL_STR_CONV);
584 0 : torture_assert(tctx, err == 0, "strtoull_err: Unexpected error");
585 :
586 0 : return true;
587 : }
588 :
589 0 : static bool test_smb_strtoul_allow_no_conversion(struct torture_context *tctx)
590 : {
591 0 : const char *number = "";
592 0 : const char *number2 = "xyz";
593 0 : unsigned long int n1 = 0;
594 0 : unsigned long long int n2 = 0;
595 : int err;
596 :
597 0 : err = 0;
598 0 : smb_strtoul(number, NULL, 0, &err, SMB_STR_ALLOW_NO_CONVERSION);
599 0 : torture_assert(tctx, err == 0, "strtoul_err: Unexpected error");
600 0 : torture_assert(tctx, n1 == 0, "strtoul_err: Unexpected value");
601 :
602 0 : err = 0;
603 0 : smb_strtoull(number, NULL, 0, &err, SMB_STR_ALLOW_NO_CONVERSION);
604 0 : torture_assert(tctx, err == 0, "strtoull_err: Unexpected error");
605 0 : torture_assert(tctx, n2 == 0, "strtoull_err: Unexpected value");
606 :
607 0 : err = 0;
608 0 : smb_strtoul(number2, NULL, 0, &err, SMB_STR_ALLOW_NO_CONVERSION);
609 0 : torture_assert(tctx, err == 0, "strtoul_err: Unexpected error");
610 0 : torture_assert(tctx, n1 == 0, "strtoul_err: Unexpected value");
611 :
612 0 : err = 0;
613 0 : smb_strtoull(number2, NULL, 0, &err, SMB_STR_ALLOW_NO_CONVERSION);
614 0 : torture_assert(tctx, err == 0, "strtoull_err: Unexpected error");
615 0 : torture_assert(tctx, n2 == 0, "strtoull_err: Unexpected value");
616 :
617 0 : return true;
618 : }
619 964 : struct torture_suite *torture_local_util(TALLOC_CTX *mem_ctx)
620 : {
621 738 : struct torture_suite *suite =
622 226 : torture_suite_create(mem_ctx, "util");
623 :
624 964 : torture_suite_add_simple_test(suite,
625 : "trim_string",
626 : test_trim_string);
627 964 : torture_suite_add_simple_test(suite,
628 : "directory_create_or_exist",
629 : test_directory_create_or_exist);
630 964 : torture_suite_add_simple_test(suite,
631 : "mem_equal_const_time",
632 : test_mem_equal_const_time);
633 964 : torture_suite_add_simple_test(suite,
634 : "smb_strtoul(l) errno",
635 : test_smb_strtoul_errno_check);
636 964 : torture_suite_add_simple_test(suite,
637 : "smb_strtoul(l) negative",
638 : test_smb_strtoul_negative);
639 964 : torture_suite_add_simple_test(suite,
640 : "smb_strtoul(l) no number",
641 : test_smb_strtoul_no_number);
642 964 : torture_suite_add_simple_test(suite,
643 : "smb_strtoul(l) allow_negative",
644 : test_smb_strtoul_allow_negative);
645 964 : torture_suite_add_simple_test(suite,
646 : "smb_strtoul(l) full string conversion",
647 : test_smb_strtoul_full_string);
648 964 : torture_suite_add_simple_test(suite,
649 : "smb_strtoul(l) allow no conversion",
650 : test_smb_strtoul_allow_no_conversion);
651 964 : return suite;
652 : }
|