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 1 : static bool test_trim_string(struct torture_context *tctx)
347 : {
348 1 : int j;
349 38 : for (j = 0; j < ARRAY_SIZE(test_trim_string_data); j++) {
350 37 : bool ret;
351 37 : const struct test_trim_string_data *d =
352 : &test_trim_string_data[j];
353 37 : char *str = talloc_strdup(tctx, d->in);
354 37 : torture_assert(tctx, d->in == NULL || str != NULL,
355 : "Out of memory");
356 :
357 37 : torture_comment(tctx, "%s\n", d->desc);
358 37 : ret = trim_string(str, d->front, d->back);
359 37 : torture_assert(tctx, ret == d->ret,
360 : "Incorrect return from trim_string()");
361 37 : if (d->out == NULL) {
362 2 : torture_assert(tctx, str == NULL, "Expected NULL");
363 : } else {
364 35 : torture_assert(tctx, str != NULL, "Expected non-NULL");
365 35 : torture_assert_str_equal(tctx, str, d->out,
366 : "Incorrect output");
367 : }
368 37 : TALLOC_FREE(str);
369 : }
370 :
371 0 : return true;
372 : }
373 :
374 1 : static bool test_directory_create_or_exist(struct torture_context *tctx)
375 : {
376 1 : char *path = NULL, *new_path = NULL, *file_path = NULL;
377 1 : bool ret = true, b = true;
378 1 : int fd;
379 1 : NTSTATUS status;
380 1 : const mode_t perms = 0741;
381 :
382 1 : status = torture_temp_dir(tctx, "util_dir", &path);;
383 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
384 : "Creating test directory failed.\n");
385 :
386 1 : b = directory_create_or_exist(path, perms);
387 1 : torture_assert_goto(tctx, b == true, ret, done,
388 : "directory_create_or_exist on "
389 : "existing directory failed.\n");
390 :
391 1 : new_path = talloc_asprintf(tctx, "%s/%s", path, "dir");
392 1 : torture_assert_goto(tctx, new_path != NULL, ret, done,
393 : "Could not allocate memory for directory path\n");
394 :
395 1 : b = directory_exist(new_path);
396 1 : torture_assert_goto(tctx, b == false, ret, done,
397 : "Check for non-existing directory failed.\n");
398 :
399 1 : b = directory_create_or_exist(new_path, perms);
400 1 : torture_assert_goto(tctx, b == true, ret, done,
401 : "directory_create_or_exist for "
402 : "new directory failed.\n");
403 :
404 1 : b = directory_exist(new_path);
405 1 : torture_assert_goto(tctx, b == true, ret, done,
406 : "Check for existing directory failed.\n");
407 :
408 1 : b = file_check_permissions(new_path, geteuid(), perms, NULL);
409 1 : torture_assert_goto(tctx, b == true, ret, done,
410 : "Permission check for directory failed.\n");
411 :
412 1 : file_path = talloc_asprintf(tctx, "%s/%s", path, "file");
413 1 : torture_assert_goto(tctx, file_path != NULL, ret, done,
414 : "Could not allocate memory for file path\n");
415 1 : fd = creat(file_path, perms);
416 1 : torture_assert_goto(tctx, fd != -1, ret, done,
417 : "Creating file failed.\n");
418 1 : close(fd);
419 :
420 1 : b = directory_create_or_exist(file_path, perms);
421 1 : torture_assert_goto(tctx, b == false, ret, done,
422 : "directory_create_or_exist for "
423 : "existing file failed.\n");
424 :
425 1 : done:
426 1 : return ret;
427 : }
428 :
429 1 : static bool test_mem_equal_const_time(struct torture_context *tctx)
430 : {
431 1 : const char *test_string = "abcdabcd";
432 :
433 1 : torture_assert(tctx, mem_equal_const_time("", "", 0),
434 : "zero-length comparison failed");
435 :
436 1 : torture_assert(tctx, mem_equal_const_time(test_string, test_string, 8),
437 : "comparison with equal pointers failed");
438 :
439 1 : torture_assert(tctx, mem_equal_const_time(test_string, test_string + 4, 4),
440 : "comparison with non-equal pointers failed");
441 :
442 1 : torture_assert(tctx, !mem_equal_const_time("abcd", "efgh", 4),
443 : "comparison with different values failed");
444 :
445 0 : return true;
446 : }
447 :
448 1 : static bool test_smb_strtoul_errno_check(struct torture_context *tctx)
449 : {
450 1 : const char *number = "123";
451 1 : unsigned long int val = 0;
452 1 : unsigned long long int vall = 0;
453 1 : int err;
454 :
455 : /* select an error code which is not set by the smb_strtoul routines */
456 1 : errno = EAGAIN;
457 1 : err = EAGAIN;
458 1 : val = smb_strtoul(number, NULL, 0, &err, SMB_STR_STANDARD);
459 1 : torture_assert(tctx, errno == EAGAIN, "smb_strtoul: Expected EAGAIN");
460 1 : torture_assert(tctx, err == 0, "smb_strtoul: Expected err = 0");
461 1 : torture_assert(tctx, val == 123, "smb_strtoul: Expected value 123");
462 :
463 : /* set err to an impossible value again before continuing */
464 1 : err = EAGAIN;
465 1 : vall = smb_strtoull(number, NULL, 0, &err, SMB_STR_STANDARD);
466 1 : torture_assert(tctx, errno == EAGAIN, "smb_strtoull: Expected EAGAIN");
467 1 : torture_assert(tctx, err == 0, "smb_strtoul: Expected err = 0");
468 1 : torture_assert(tctx, vall == 123, "smb_strtoul: Expected value 123");
469 :
470 0 : return true;
471 : }
472 :
473 1 : static bool test_smb_strtoul_negative(struct torture_context *tctx)
474 : {
475 1 : const char *number = "-132";
476 1 : const char *number2 = "132-";
477 1 : unsigned long int val = 0;
478 1 : unsigned long long int vall = 0;
479 1 : int err;
480 :
481 1 : err = 0;
482 1 : smb_strtoul(number, NULL, 0, &err, SMB_STR_STANDARD);
483 1 : torture_assert(tctx, err == EINVAL, "smb_strtoul: Expected EINVAL");
484 :
485 1 : err = 0;
486 1 : smb_strtoull(number, NULL, 0, &err, SMB_STR_STANDARD);
487 1 : 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 1 : err = 0;
495 1 : val = smb_strtoul(number2, NULL, 0, &err, SMB_STR_STANDARD);
496 1 : torture_assert(tctx, err == 0, "smb_strtoul: Expected no error");
497 1 : torture_assert(tctx, val == 132, "smb_strtoul: Wrong value");
498 :
499 1 : err = 0;
500 1 : vall = smb_strtoull(number2, NULL, 0, &err, SMB_STR_STANDARD);
501 1 : torture_assert(tctx, err == 0, "smb_strtoull: Expected no error");
502 1 : torture_assert(tctx, vall == 132, "smb_strtoull: Wrong value");
503 :
504 0 : return true;
505 : }
506 :
507 1 : static bool test_smb_strtoul_no_number(struct torture_context *tctx)
508 : {
509 1 : const char *number = "ghijk";
510 1 : const char *blank = "";
511 1 : int err;
512 :
513 1 : err = 0;
514 1 : smb_strtoul(number, NULL, 0, &err, SMB_STR_STANDARD);
515 1 : torture_assert(tctx, err == EINVAL, "smb_strtoul: Expected EINVAL");
516 :
517 1 : err = 0;
518 1 : smb_strtoull(number, NULL, 0, &err, SMB_STR_STANDARD);
519 1 : torture_assert(tctx, err == EINVAL, "smb_strtoull: Expected EINVAL");
520 :
521 1 : err = 0;
522 1 : smb_strtoul(blank, NULL, 0, &err, SMB_STR_STANDARD);
523 1 : torture_assert(tctx, err == EINVAL, "smb_strtoul: Expected EINVAL");
524 :
525 1 : err = 0;
526 1 : smb_strtoull(blank, NULL, 0, &err, SMB_STR_STANDARD);
527 1 : torture_assert(tctx, err == EINVAL, "smb_strtoull: Expected EINVAL");
528 :
529 0 : return true;
530 : }
531 :
532 1 : static bool test_smb_strtoul_allow_negative(struct torture_context *tctx)
533 : {
534 1 : const char *number = "-1";
535 1 : const char *number2 = "-1-1";
536 1 : unsigned long res = 0;
537 1 : unsigned long long res2 = 0;
538 1 : char *end_ptr = NULL;
539 1 : int err;
540 :
541 1 : err = 0;
542 1 : res = smb_strtoul(number, NULL, 0, &err, SMB_STR_ALLOW_NEGATIVE);
543 1 : torture_assert(tctx, err == 0, "strtoul_err: Unexpected error");
544 1 : torture_assert(tctx, res == ULONG_MAX, "strtoul_err: Unexpected value");
545 :
546 1 : err = 0;
547 1 : res2 = smb_strtoull(number, NULL, 0, &err, SMB_STR_ALLOW_NEGATIVE);
548 1 : torture_assert(tctx, err == 0, "strtoull_err: Unexpected error");
549 1 : torture_assert(tctx, res2 == ULLONG_MAX, "strtoull_err: Unexpected value");
550 :
551 1 : err = 0;
552 1 : smb_strtoul(number2, &end_ptr, 0, &err, SMB_STR_ALLOW_NEGATIVE);
553 1 : torture_assert(tctx, err == 0, "strtoul_err: Unexpected error");
554 1 : torture_assert(tctx, end_ptr[0] == '-', "strtoul_err: Unexpected end pointer");
555 :
556 1 : err = 0;
557 1 : smb_strtoull(number2, &end_ptr, 0, &err, SMB_STR_ALLOW_NEGATIVE);
558 1 : torture_assert(tctx, err == 0, "strtoull_err: Unexpected error");
559 1 : torture_assert(tctx, end_ptr[0] == '-', "strtoull_err: Unexpected end pointer");
560 :
561 0 : return true;
562 : }
563 :
564 1 : static bool test_smb_strtoul_full_string(struct torture_context *tctx)
565 : {
566 1 : const char *number = "123 ";
567 1 : const char *number2 = "123";
568 1 : int err;
569 :
570 1 : err = 0;
571 1 : smb_strtoul(number, NULL, 0, &err, SMB_STR_FULL_STR_CONV);
572 1 : torture_assert(tctx, err == EINVAL, "strtoul_err: Expected EINVAL");
573 :
574 1 : err = 0;
575 1 : smb_strtoull(number, NULL, 0, &err, SMB_STR_FULL_STR_CONV);
576 1 : torture_assert(tctx, err == EINVAL, "strtoull_err: Expected EINVAL");
577 :
578 1 : err = 0;
579 1 : smb_strtoul(number2, NULL, 0, &err, SMB_STR_FULL_STR_CONV);
580 1 : torture_assert(tctx, err == 0, "strtoul_err: Unexpected error");
581 :
582 1 : err = 0;
583 1 : smb_strtoull(number2, NULL, 0, &err, SMB_STR_FULL_STR_CONV);
584 1 : torture_assert(tctx, err == 0, "strtoull_err: Unexpected error");
585 :
586 0 : return true;
587 : }
588 :
589 1 : static bool test_smb_strtoul_allow_no_conversion(struct torture_context *tctx)
590 : {
591 1 : const char *number = "";
592 1 : const char *number2 = "xyz";
593 1 : unsigned long int n1 = 0;
594 1 : unsigned long long int n2 = 0;
595 1 : int err;
596 :
597 1 : err = 0;
598 1 : smb_strtoul(number, NULL, 0, &err, SMB_STR_ALLOW_NO_CONVERSION);
599 1 : torture_assert(tctx, err == 0, "strtoul_err: Unexpected error");
600 1 : torture_assert(tctx, n1 == 0, "strtoul_err: Unexpected value");
601 :
602 1 : err = 0;
603 1 : smb_strtoull(number, NULL, 0, &err, SMB_STR_ALLOW_NO_CONVERSION);
604 1 : torture_assert(tctx, err == 0, "strtoull_err: Unexpected error");
605 1 : torture_assert(tctx, n2 == 0, "strtoull_err: Unexpected value");
606 :
607 1 : err = 0;
608 1 : smb_strtoul(number2, NULL, 0, &err, SMB_STR_ALLOW_NO_CONVERSION);
609 1 : torture_assert(tctx, err == 0, "strtoul_err: Unexpected error");
610 1 : torture_assert(tctx, n1 == 0, "strtoul_err: Unexpected value");
611 :
612 1 : err = 0;
613 1 : smb_strtoull(number2, NULL, 0, &err, SMB_STR_ALLOW_NO_CONVERSION);
614 1 : 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 2354 : struct torture_suite *torture_local_util(TALLOC_CTX *mem_ctx)
620 : {
621 125 : struct torture_suite *suite =
622 2354 : torture_suite_create(mem_ctx, "util");
623 :
624 2354 : torture_suite_add_simple_test(suite,
625 : "trim_string",
626 : test_trim_string);
627 2354 : torture_suite_add_simple_test(suite,
628 : "directory_create_or_exist",
629 : test_directory_create_or_exist);
630 2354 : torture_suite_add_simple_test(suite,
631 : "mem_equal_const_time",
632 : test_mem_equal_const_time);
633 2354 : torture_suite_add_simple_test(suite,
634 : "smb_strtoul(l) errno",
635 : test_smb_strtoul_errno_check);
636 2354 : torture_suite_add_simple_test(suite,
637 : "smb_strtoul(l) negative",
638 : test_smb_strtoul_negative);
639 2354 : torture_suite_add_simple_test(suite,
640 : "smb_strtoul(l) no number",
641 : test_smb_strtoul_no_number);
642 2354 : torture_suite_add_simple_test(suite,
643 : "smb_strtoul(l) allow_negative",
644 : test_smb_strtoul_allow_negative);
645 2354 : torture_suite_add_simple_test(suite,
646 : "smb_strtoul(l) full string conversion",
647 : test_smb_strtoul_full_string);
648 2354 : torture_suite_add_simple_test(suite,
649 : "smb_strtoul(l) allow no conversion",
650 : test_smb_strtoul_allow_no_conversion);
651 2354 : return suite;
652 : }
|