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
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.
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.
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/>.
25 #include "system/filesys.h"
27 #include "libcli/util/ntstatus.h"
28 #include "torture/torture.h"
29 #include "lib/util/data_blob.h"
30 #include "torture/local/proto.h"
32 #include "lib/util/samba_util.h"
33 #include "lib/util/smb_strtox.h"
38 struct test_trim_string_data
{
47 static const struct test_trim_string_data test_trim_string_data
[] = {
81 .desc
= "Trim front, non-matching",
89 .desc
= "Trim front, matches back",
97 .desc
= "Trim front, partial-match",
105 .desc
= "Trim front, too long",
113 .desc
= "Trim front, 1 char, 1x",
121 .desc
= "Trim front, 1 char, 2x",
129 .desc
= "Trim front, 1 char, 3x",
137 .desc
= "Trim front, 1 char, matches all",
145 .desc
= "Trim front, 2 chars, 1x",
153 .desc
= "Trim front, 2 chars, 2x",
161 .desc
= "Trim front, 3 chars, matches all",
169 .desc
= "Trim back, non-matching",
177 .desc
= "Trim back, matches front",
185 .desc
= "Trim back, partial-match",
193 .desc
= "Trim back, too long",
201 .desc
= "Trim back, 1 char, 1x",
209 .desc
= "Trim back, 1 char, 2x",
217 .desc
= "Trim back, 1 char, 3x",
225 .desc
= "Trim back, 1 char, matches all",
233 .desc
= "Trim back, 2 chars, 1x",
241 .desc
= "Trim back, 2 chars, 2x",
249 .desc
= "Trim back, 3 chars, matches all",
257 .desc
= "Trim both, non-matching",
265 .desc
= "Trim both, reversed",
273 .desc
= "Trim both, 1 char, 1x",
281 .desc
= "Trim both, 1 char, 2x",
289 .desc
= "Trim both, 1 char, 3x",
297 .desc
= "Trim both, 1 char, matches all",
305 .desc
= "Trim both, 2 chars, 1x",
313 .desc
= "Trim both, 2 chars, 2x",
321 .desc
= "Trim both, 2 chars, front matches, back doesn't",
329 .desc
= "Trim both, 2 chars, back matches, front doesn't",
337 .desc
= "Trim back, 3 chars, matches all",
346 static bool test_trim_string(struct torture_context
*tctx
)
349 for (j
= 0; j
< ARRAY_SIZE(test_trim_string_data
); j
++) {
351 const struct test_trim_string_data
*d
=
352 &test_trim_string_data
[j
];
353 char *str
= talloc_strdup(tctx
, d
->in
);
354 torture_assert(tctx
, d
->in
== NULL
|| str
!= NULL
,
357 torture_comment(tctx
, "%s\n", d
->desc
);
358 ret
= trim_string(str
, d
->front
, d
->back
);
359 torture_assert(tctx
, ret
== d
->ret
,
360 "Incorrect return from trim_string()");
361 if (d
->out
== NULL
) {
362 torture_assert(tctx
, str
== NULL
, "Expected NULL");
364 torture_assert(tctx
, str
!= NULL
, "Expected non-NULL");
365 torture_assert_str_equal(tctx
, str
, d
->out
,
374 static bool test_directory_create_or_exist(struct torture_context
*tctx
)
376 char *path
= NULL
, *new_path
= NULL
, *file_path
= NULL
;
377 bool ret
= true, b
= true;
380 const mode_t perms
= 0741;
382 status
= torture_temp_dir(tctx
, "util_dir", &path
);;
383 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
384 "Creating test directory failed.\n");
386 b
= directory_create_or_exist(path
, perms
);
387 torture_assert_goto(tctx
, b
== true, ret
, done
,
388 "directory_create_or_exist on "
389 "existing directory failed.\n");
391 new_path
= talloc_asprintf(tctx
, "%s/%s", path
, "dir");
392 torture_assert_goto(tctx
, new_path
!= NULL
, ret
, done
,
393 "Could not allocate memory for directory path\n");
395 b
= directory_exist(new_path
);
396 torture_assert_goto(tctx
, b
== false, ret
, done
,
397 "Check for non-existing directory failed.\n");
399 b
= directory_create_or_exist(new_path
, perms
);
400 torture_assert_goto(tctx
, b
== true, ret
, done
,
401 "directory_create_or_exist for "
402 "new directory failed.\n");
404 b
= directory_exist(new_path
);
405 torture_assert_goto(tctx
, b
== true, ret
, done
,
406 "Check for existing directory failed.\n");
408 b
= file_check_permissions(new_path
, geteuid(), perms
, NULL
);
409 torture_assert_goto(tctx
, b
== true, ret
, done
,
410 "Permission check for directory failed.\n");
412 file_path
= talloc_asprintf(tctx
, "%s/%s", path
, "file");
413 torture_assert_goto(tctx
, file_path
!= NULL
, ret
, done
,
414 "Could not allocate memory for file path\n");
415 fd
= creat(file_path
, perms
);
416 torture_assert_goto(tctx
, fd
!= -1, ret
, done
,
417 "Creating file failed.\n");
420 b
= directory_create_or_exist(file_path
, perms
);
421 torture_assert_goto(tctx
, b
== false, ret
, done
,
422 "directory_create_or_exist for "
423 "existing file failed.\n");
429 static bool test_mem_equal_const_time(struct torture_context
*tctx
)
431 const char *test_string
= "abcdabcd";
433 torture_assert(tctx
, mem_equal_const_time("", "", 0),
434 "zero-length comparison failed");
436 torture_assert(tctx
, mem_equal_const_time(test_string
, test_string
, 8),
437 "comparison with equal pointers failed");
439 torture_assert(tctx
, mem_equal_const_time(test_string
, test_string
+ 4, 4),
440 "comparison with non-equal pointers failed");
442 torture_assert(tctx
, !mem_equal_const_time("abcd", "efgh", 4),
443 "comparison with different values failed");
448 static bool test_smb_strtoul_errno_check(struct torture_context
*tctx
)
450 const char *number
= "123";
451 unsigned long int val
= 0;
452 unsigned long long int vall
= 0;
455 /* select an error code which is not set by the smb_strtoul routines */
458 val
= smb_strtoul(number
, NULL
, 0, &err
, SMB_STR_STANDARD
);
459 torture_assert(tctx
, errno
== EAGAIN
, "smb_strtoul: Expected EAGAIN");
460 torture_assert(tctx
, err
== 0, "smb_strtoul: Expected err = 0");
461 torture_assert(tctx
, val
== 123, "smb_strtoul: Expected value 123");
463 /* set err to an impossible value again before continuing */
465 vall
= smb_strtoull(number
, NULL
, 0, &err
, SMB_STR_STANDARD
);
466 torture_assert(tctx
, errno
== EAGAIN
, "smb_strtoull: Expected EAGAIN");
467 torture_assert(tctx
, err
== 0, "smb_strtoul: Expected err = 0");
468 torture_assert(tctx
, vall
== 123, "smb_strtoul: Expected value 123");
473 static bool test_smb_strtoul_negative(struct torture_context
*tctx
)
475 const char *number
= "-132";
476 const char *number2
= "132-";
477 unsigned long int val
= 0;
478 unsigned long long int vall
= 0;
482 smb_strtoul(number
, NULL
, 0, &err
, SMB_STR_STANDARD
);
483 torture_assert(tctx
, err
== EINVAL
, "smb_strtoul: Expected EINVAL");
486 smb_strtoull(number
, NULL
, 0, &err
, SMB_STR_STANDARD
);
487 torture_assert(tctx
, err
== EINVAL
, "smb_strtoull: Expected EINVAL");
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.
495 val
= smb_strtoul(number2
, NULL
, 0, &err
, SMB_STR_STANDARD
);
496 torture_assert(tctx
, err
== 0, "smb_strtoul: Expected no error");
497 torture_assert(tctx
, val
== 132, "smb_strtoul: Wrong value");
500 vall
= smb_strtoull(number2
, NULL
, 0, &err
, SMB_STR_STANDARD
);
501 torture_assert(tctx
, err
== 0, "smb_strtoull: Expected no error");
502 torture_assert(tctx
, vall
== 132, "smb_strtoull: Wrong value");
507 static bool test_smb_strtoul_no_number(struct torture_context
*tctx
)
509 const char *number
= "ghijk";
510 const char *blank
= "";
514 smb_strtoul(number
, NULL
, 0, &err
, SMB_STR_STANDARD
);
515 torture_assert(tctx
, err
== EINVAL
, "smb_strtoul: Expected EINVAL");
518 smb_strtoull(number
, NULL
, 0, &err
, SMB_STR_STANDARD
);
519 torture_assert(tctx
, err
== EINVAL
, "smb_strtoull: Expected EINVAL");
522 smb_strtoul(blank
, NULL
, 0, &err
, SMB_STR_STANDARD
);
523 torture_assert(tctx
, err
== EINVAL
, "smb_strtoul: Expected EINVAL");
526 smb_strtoull(blank
, NULL
, 0, &err
, SMB_STR_STANDARD
);
527 torture_assert(tctx
, err
== EINVAL
, "smb_strtoull: Expected EINVAL");
532 static bool test_smb_strtoul_allow_negative(struct torture_context
*tctx
)
534 const char *number
= "-1";
535 const char *number2
= "-1-1";
536 unsigned long res
= 0;
537 unsigned long long res2
= 0;
538 char *end_ptr
= NULL
;
542 res
= smb_strtoul(number
, NULL
, 0, &err
, SMB_STR_ALLOW_NEGATIVE
);
543 torture_assert(tctx
, err
== 0, "strtoul_err: Unexpected error");
544 torture_assert(tctx
, res
== ULONG_MAX
, "strtoul_err: Unexpected value");
547 res2
= smb_strtoull(number
, NULL
, 0, &err
, SMB_STR_ALLOW_NEGATIVE
);
548 torture_assert(tctx
, err
== 0, "strtoull_err: Unexpected error");
549 torture_assert(tctx
, res2
== ULLONG_MAX
, "strtoull_err: Unexpected value");
552 smb_strtoul(number2
, &end_ptr
, 0, &err
, SMB_STR_ALLOW_NEGATIVE
);
553 torture_assert(tctx
, err
== 0, "strtoul_err: Unexpected error");
554 torture_assert(tctx
, end_ptr
[0] == '-', "strtoul_err: Unexpected end pointer");
557 smb_strtoull(number2
, &end_ptr
, 0, &err
, SMB_STR_ALLOW_NEGATIVE
);
558 torture_assert(tctx
, err
== 0, "strtoull_err: Unexpected error");
559 torture_assert(tctx
, end_ptr
[0] == '-', "strtoull_err: Unexpected end pointer");
564 static bool test_smb_strtoul_full_string(struct torture_context
*tctx
)
566 const char *number
= "123 ";
567 const char *number2
= "123";
571 smb_strtoul(number
, NULL
, 0, &err
, SMB_STR_FULL_STR_CONV
);
572 torture_assert(tctx
, err
== EINVAL
, "strtoul_err: Expected EINVAL");
575 smb_strtoull(number
, NULL
, 0, &err
, SMB_STR_FULL_STR_CONV
);
576 torture_assert(tctx
, err
== EINVAL
, "strtoull_err: Expected EINVAL");
579 smb_strtoul(number2
, NULL
, 0, &err
, SMB_STR_FULL_STR_CONV
);
580 torture_assert(tctx
, err
== 0, "strtoul_err: Unexpected error");
583 smb_strtoull(number2
, NULL
, 0, &err
, SMB_STR_FULL_STR_CONV
);
584 torture_assert(tctx
, err
== 0, "strtoull_err: Unexpected error");
589 static bool test_smb_strtoul_allow_no_conversion(struct torture_context
*tctx
)
591 const char *number
= "";
592 const char *number2
= "xyz";
593 unsigned long int n1
= 0;
594 unsigned long long int n2
= 0;
598 smb_strtoul(number
, NULL
, 0, &err
, SMB_STR_ALLOW_NO_CONVERSION
);
599 torture_assert(tctx
, err
== 0, "strtoul_err: Unexpected error");
600 torture_assert(tctx
, n1
== 0, "strtoul_err: Unexpected value");
603 smb_strtoull(number
, NULL
, 0, &err
, SMB_STR_ALLOW_NO_CONVERSION
);
604 torture_assert(tctx
, err
== 0, "strtoull_err: Unexpected error");
605 torture_assert(tctx
, n2
== 0, "strtoull_err: Unexpected value");
608 smb_strtoul(number2
, NULL
, 0, &err
, SMB_STR_ALLOW_NO_CONVERSION
);
609 torture_assert(tctx
, err
== 0, "strtoul_err: Unexpected error");
610 torture_assert(tctx
, n1
== 0, "strtoul_err: Unexpected value");
613 smb_strtoull(number2
, NULL
, 0, &err
, SMB_STR_ALLOW_NO_CONVERSION
);
614 torture_assert(tctx
, err
== 0, "strtoull_err: Unexpected error");
615 torture_assert(tctx
, n2
== 0, "strtoull_err: Unexpected value");
619 struct torture_suite
*torture_local_util(TALLOC_CTX
*mem_ctx
)
621 struct torture_suite
*suite
=
622 torture_suite_create(mem_ctx
, "util");
624 torture_suite_add_simple_test(suite
,
627 torture_suite_add_simple_test(suite
,
628 "directory_create_or_exist",
629 test_directory_create_or_exist
);
630 torture_suite_add_simple_test(suite
,
631 "mem_equal_const_time",
632 test_mem_equal_const_time
);
633 torture_suite_add_simple_test(suite
,
634 "smb_strtoul(l) errno",
635 test_smb_strtoul_errno_check
);
636 torture_suite_add_simple_test(suite
,
637 "smb_strtoul(l) negative",
638 test_smb_strtoul_negative
);
639 torture_suite_add_simple_test(suite
,
640 "smb_strtoul(l) no number",
641 test_smb_strtoul_no_number
);
642 torture_suite_add_simple_test(suite
,
643 "smb_strtoul(l) allow_negative",
644 test_smb_strtoul_allow_negative
);
645 torture_suite_add_simple_test(suite
,
646 "smb_strtoul(l) full string conversion",
647 test_smb_strtoul_full_string
);
648 torture_suite_add_simple_test(suite
,
649 "smb_strtoul(l) allow no conversion",
650 test_smb_strtoul_allow_no_conversion
);