mirror of
https://git.proxmox.com/git/efi-boot-shim
synced 2025-05-29 17:38:35 +00:00
1499 lines
52 KiB
C
1499 lines
52 KiB
C
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
/*
|
|
* test-str.c - test our string functions.
|
|
*/
|
|
#pragma GCC diagnostic ignored "-Wunused-variable"
|
|
#pragma GCC diagnostic error "-Wnonnull"
|
|
#pragma GCC diagnostic error "-Wunused-function"
|
|
|
|
#pragma GCC diagnostic warning "-Wcpp"
|
|
|
|
#ifndef SHIM_UNIT_TEST
|
|
#define SHIM_UNIT_TEST
|
|
#endif
|
|
#include "shim.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
static int
|
|
test_strlen(void)
|
|
{
|
|
const char s1[] = "abcd";
|
|
const char s2[] = "";
|
|
|
|
assert_equal_return(shim_strlen(s1), 4, -1, "got %d expected %d\n");
|
|
assert_equal_return(strlen(s1), 4, -1, "got %d expected %d\n");
|
|
assert_equal_return(shim_strlen(s2), 0, -1, "got %d expected %d\n");
|
|
assert_equal_return(strlen(s2), 0, -1, "got %d expected %d\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
test_strnlen(void)
|
|
{
|
|
const char s1[] = "abcd";
|
|
const char s2[] = "";
|
|
|
|
assert_equal_return(shim_strnlen(s1, 0), 0, -1, "got %d expected %d\n");
|
|
assert_equal_return(strnlen(s1, 0), 0, -1, "got %d expected %d\n");
|
|
assert_equal_return(shim_strnlen(s1, 1), 1, -1, "got %d expected %d\n");
|
|
assert_equal_return(strnlen(s1, 1), 1, -1, "got %d expected %d\n");
|
|
assert_equal_return(shim_strnlen(s1, 3), 3, -1, "got %d expected %d\n");
|
|
assert_equal_return(strnlen(s1, 3), 3, -1, "got %d expected %d\n");
|
|
assert_equal_return(shim_strnlen(s1, 4), 4, -1, "got %d expected %d\n");
|
|
assert_equal_return(strnlen(s1, 4), 4, -1, "got %d expected %d\n");
|
|
assert_equal_return(shim_strnlen(s1, 5), 4, -1, "got %d expected %d\n");
|
|
assert_equal_return(strnlen(s1, 5), 4, -1, "got %d expected %d\n");
|
|
assert_equal_return(shim_strnlen(s2, 0), 0, -1, "got %d expected %d\n");
|
|
assert_equal_return(strnlen(s2, 0), 0, -1, "got %d expected %d\n");
|
|
assert_equal_return(shim_strnlen(s2, 1), 0, -1, "got %d expected %d\n");
|
|
assert_equal_return(strnlen(s2, 1), 0, -1, "got %d expected %d\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wshadow"
|
|
|
|
/*
|
|
* these are constants so that the failures are readable if you get
|
|
* it wrong.
|
|
*/
|
|
#define s0 "sbat,"
|
|
#define s0sz 6
|
|
#define s0len 5
|
|
#define s1 "sbat,1,2021030218"
|
|
#define s1sz 18
|
|
#define s1len 17
|
|
#define s2 "sbat,1,20210302"
|
|
#define s2sz 16
|
|
#define s2len 15
|
|
#define s3 "sbat,1,20210303"
|
|
#define s3sz 16
|
|
#define s3len 15
|
|
#define s4 "sbat\314\234\014,"
|
|
#define s4sz 9
|
|
#define s4len 8
|
|
/*
|
|
* same as s4 but with a UTF8 encoding error; one bit is cleared.
|
|
*/
|
|
#define s5 "sbat\314\034\014,"
|
|
#define s5sz 9
|
|
#define s5len 8
|
|
|
|
#define test_strcmp_helper(fn, invert_sign_errors, invert_encoding_errors) \
|
|
({ \
|
|
printf("testing %s\n", #fn); \
|
|
int status_ = 0, rc_; \
|
|
\
|
|
rc_ = assert_zero_as_expr(fn(s0, s0), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
\
|
|
if (invert_sign_errors) \
|
|
rc_ = assert_positive_as_expr(fn(s0, s1), -1, "\n"); \
|
|
else \
|
|
rc_ = assert_negative_as_expr(fn(s0, s1), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
rc_ = assert_positive_as_expr(fn(s1, s0), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
\
|
|
rc_ = assert_positive_as_expr(fn(s1, s2), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (invert_sign_errors) \
|
|
rc_ = assert_positive_as_expr(fn(s2, s1), -1, "\n"); \
|
|
else \
|
|
rc_ = assert_negative_as_expr(fn(s2, s1), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
\
|
|
if (invert_sign_errors) \
|
|
rc_ = assert_positive_as_expr(fn(s2, s3), -1, "\n"); \
|
|
else \
|
|
rc_ = assert_negative_as_expr(fn(s2, s3), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
rc_ = assert_positive_as_expr(fn(s3, s2), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
\
|
|
if (invert_encoding_errors) \
|
|
rc_ = assert_negative_as_expr(fn(s4, s5), -1, "\n"); \
|
|
else \
|
|
rc_ = assert_positive_as_expr(fn(s4, s5), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
\
|
|
if (status_ < 0) \
|
|
printf("%s failed\n", #fn); \
|
|
status_; \
|
|
})
|
|
|
|
static int
|
|
test_strcmp(void)
|
|
{
|
|
int status = 0;
|
|
int rc;
|
|
|
|
/*
|
|
* shim's strcmp
|
|
*/
|
|
rc = test_strcmp_helper(shim_strcmp, false, false);
|
|
status = MIN(rc, status);
|
|
|
|
/*
|
|
* libc's strcmp
|
|
*/
|
|
rc = test_strcmp_helper(strcmp, false, false);
|
|
status = MIN(rc, status);
|
|
|
|
return status;
|
|
}
|
|
|
|
#undef s0
|
|
#undef s0sz
|
|
#undef s0len
|
|
#undef s1
|
|
#undef s1sz
|
|
#undef s1len
|
|
#undef s2
|
|
#undef s2sz
|
|
#undef s2len
|
|
#undef s3
|
|
#undef s3sz
|
|
#undef s3len
|
|
#undef s4
|
|
#undef s4sz
|
|
#undef s4len
|
|
#undef s5
|
|
#undef s5sz
|
|
#undef s5len
|
|
|
|
/*
|
|
* these are constants so that the failures are readable if you get
|
|
* it wrong.
|
|
*/
|
|
#define s0 "sbAt,"
|
|
#define s0sz 6
|
|
#define s0len 5
|
|
#define s1 "sbaT,1,2021030218"
|
|
#define s1sz 18
|
|
#define s1len 17
|
|
#define s2 "sbAt,1,20210302"
|
|
#define s2sz 16
|
|
#define s2len 15
|
|
#define s3 "sbaT,1,20210303"
|
|
#define s3sz 16
|
|
#define s3len 15
|
|
#define s4 "sbat\314\234\014,"
|
|
#define s4sz 9
|
|
#define s4len 8
|
|
/*
|
|
* same as s4 but with a UTF8 encoding error; one bit is cleared.
|
|
*/
|
|
#define s5 "sbat\314\034\014,"
|
|
#define s5sz 9
|
|
#define s5len 8
|
|
|
|
#define test_strcasecmp_helper(fn, invert_sign_errors, invert_encoding_errors) \
|
|
({ \
|
|
printf("testing %s\n", #fn); \
|
|
int status_ = 0, rc_; \
|
|
\
|
|
rc_ = assert_zero_as_expr(fn(s0, s0), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
\
|
|
if (invert_sign_errors) \
|
|
rc_ = assert_positive_as_expr(fn(s0, s1), -1, "\n"); \
|
|
else \
|
|
rc_ = assert_negative_as_expr(fn(s0, s1), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
rc_ = assert_positive_as_expr(fn(s1, s0), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
\
|
|
rc_ = assert_positive_as_expr(fn(s1, s2), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (invert_sign_errors) \
|
|
rc_ = assert_positive_as_expr(fn(s2, s1), -1, "\n"); \
|
|
else \
|
|
rc_ = assert_negative_as_expr(fn(s2, s1), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
\
|
|
if (invert_sign_errors) \
|
|
rc_ = assert_positive_as_expr(fn(s2, s3), -1, "\n"); \
|
|
else \
|
|
rc_ = assert_negative_as_expr(fn(s2, s3), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
rc_ = assert_positive_as_expr(fn(s3, s2), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
\
|
|
if (invert_encoding_errors) \
|
|
rc_ = assert_negative_as_expr(fn(s4, s5), -1, "\n"); \
|
|
else \
|
|
rc_ = assert_positive_as_expr(fn(s4, s5), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
\
|
|
if (status_ < 0) \
|
|
printf("%s failed\n", #fn); \
|
|
status_; \
|
|
})
|
|
|
|
static int
|
|
test_strcasecmp(void)
|
|
{
|
|
int status = 0;
|
|
int rc;
|
|
|
|
/*
|
|
* shim's strcasecmp
|
|
*/
|
|
rc = test_strcasecmp_helper(shim_strcasecmp, false, false);
|
|
status = MIN(rc, status);
|
|
|
|
/*
|
|
* libc's strcasecmp
|
|
*/
|
|
rc = test_strcasecmp_helper(strcasecmp, false, false);
|
|
status = MIN(rc, status);
|
|
|
|
return status;
|
|
}
|
|
|
|
#undef s0
|
|
#undef s0sz
|
|
#undef s0len
|
|
#undef s1
|
|
#undef s1sz
|
|
#undef s1len
|
|
#undef s2
|
|
#undef s2sz
|
|
#undef s2len
|
|
#undef s3
|
|
#undef s3sz
|
|
#undef s3len
|
|
#undef s4
|
|
#undef s4sz
|
|
#undef s4len
|
|
#undef s5
|
|
#undef s5sz
|
|
#undef s5len
|
|
|
|
/*
|
|
* these are constants so that the failures are readable if you get
|
|
* it wrong.
|
|
*/
|
|
#define s0 "sbAt,"
|
|
#define s0sz 6
|
|
#define s0len 5
|
|
#define s1 "sbaT,1,2021030218"
|
|
#define s1sz 18
|
|
#define s1len 17
|
|
#define s2 "sbAt,1,20210302"
|
|
#define s2sz 16
|
|
#define s2len 15
|
|
#define s3 "sbaT,1,20210303"
|
|
#define s3sz 16
|
|
#define s3len 15
|
|
#define s4 "sbat\314\234\014,"
|
|
#define s4sz 9
|
|
#define s4len 8
|
|
/*
|
|
* same as s4 but with a UTF8 encoding error; one bit is cleared.
|
|
*/
|
|
#define s5 "sbat\314\034\014,"
|
|
#define s5sz 9
|
|
#define s5len 8
|
|
|
|
#define test_strncasecmp_helper(fn, test_cmp_magnitude, invert_sign_errors, \
|
|
invert_encoding_errors) \
|
|
({ \
|
|
printf("testing %s\n", #fn); \
|
|
int status_ = 0, rc_; \
|
|
\
|
|
rc_ = assert_zero_as_expr(fn(s0, s0, s0len), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
rc_ = assert_zero_as_expr(fn(s0, s0, s0sz), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
\
|
|
rc_ = assert_zero_as_expr(fn(s0, s1, s0len), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (invert_sign_errors) \
|
|
rc_ = assert_positive_as_expr(fn(s0, s1, s0sz), -1, \
|
|
"\n"); \
|
|
else \
|
|
rc_ = assert_negative_as_expr(fn(s0, s1, s0sz), -1, \
|
|
"\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (test_cmp_magnitude) { \
|
|
rc_ = assert_equal_as_expr(fn(s0, s1, s0sz), \
|
|
s0[s0len] - s1[s0len], -1, \
|
|
"expected %d got %d\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
} \
|
|
rc_ = assert_positive_as_expr(fn(s1, s0, s0sz), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (test_cmp_magnitude) { \
|
|
rc_ = assert_equal_as_expr(fn(s1, s0, s0sz), \
|
|
s1[s0len] - s0[s0len], -1, \
|
|
"expected %d got %d\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
} \
|
|
\
|
|
rc_ = assert_positive_as_expr(fn(s1, s2, s1sz), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (test_cmp_magnitude) { \
|
|
rc_ = assert_equal_as_expr(fn(s1, s2, s2sz), \
|
|
s1[s2len] - s2[s2len], -1, \
|
|
"expected %d got %d\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
} \
|
|
rc_ = assert_positive_as_expr(fn(s1, s2, s1len), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (test_cmp_magnitude) { \
|
|
rc_ = assert_equal_as_expr( \
|
|
fn(s1, s2, s2len), \
|
|
s1[s2len - 1] - s2[s2len - 1], -1, \
|
|
"expected %d got %d\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
} \
|
|
if (invert_sign_errors) \
|
|
rc_ = assert_positive_as_expr(fn(s2, s1, s1sz), -1, \
|
|
"\n"); \
|
|
else \
|
|
rc_ = assert_negative_as_expr(fn(s2, s1, s1sz), -1, \
|
|
"\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (test_cmp_magnitude) { \
|
|
rc_ = assert_equal_as_expr(fn(s2, s1, s1sz), \
|
|
s2[s2len] - s1[s2len], -1, \
|
|
"expected %d got %d\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
} \
|
|
\
|
|
rc_ = assert_zero_as_expr(fn(s1, s2, s2len), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
rc_ = assert_positive_as_expr(fn(s1, s2, s2sz), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (test_cmp_magnitude) { \
|
|
rc_ = assert_equal_as_expr(fn(s1, s2, s2sz), \
|
|
s1[s2len] - s2[s2len], -1, \
|
|
"expected %d got %d\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
} \
|
|
\
|
|
if (invert_sign_errors) \
|
|
rc_ = assert_positive_as_expr(fn(s2, s3, s2sz), -1, \
|
|
"\n"); \
|
|
else \
|
|
rc_ = assert_negative_as_expr(fn(s2, s3, s2sz), -1, \
|
|
"\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
rc_ = assert_equal_as_expr(fn(s2, s3, s2sz), \
|
|
s2[s2len - 1] - s3[s2len - 1], -1, \
|
|
"expected %d got %d\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
rc_ = assert_equal_as_expr(fn(s2, s3, s2len), \
|
|
s2[s2len - 1] - s3[s2len - 1], -1, \
|
|
"expected %d got %d\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (invert_sign_errors) \
|
|
rc_ = assert_positive_as_expr(fn(s2, s3, s2len), -1, \
|
|
"\n"); \
|
|
else \
|
|
rc_ = assert_negative_as_expr(fn(s2, s3, s2len), -1, \
|
|
"\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
rc_ = assert_zero_as_expr(fn(s2, s3, s2len - 1), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
rc_ = assert_false_as_expr(fn(s1, s2, s2len), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
\
|
|
if (invert_encoding_errors) \
|
|
rc_ = assert_negative_as_expr(fn(s4, s5, s4sz), -1, \
|
|
"\n"); \
|
|
else \
|
|
rc_ = assert_positive_as_expr(fn(s4, s5, s4sz), -1, \
|
|
"\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
\
|
|
if (status_ < 0) \
|
|
printf("%s failed\n", #fn); \
|
|
status_; \
|
|
})
|
|
|
|
static int
|
|
test_strncasecmp(void)
|
|
{
|
|
int status = 0;
|
|
int rc;
|
|
|
|
/*
|
|
* shim's strncasecmp
|
|
*/
|
|
rc = test_strncasecmp_helper(shim_strncasecmp, true, false, false);
|
|
status = MIN(rc, status);
|
|
|
|
/*
|
|
* libc's strncasecmp
|
|
*/
|
|
rc = test_strncasecmp_helper(strncasecmp, false, false, false);
|
|
status = MIN(rc, status);
|
|
|
|
return status;
|
|
}
|
|
|
|
#undef s0
|
|
#undef s0sz
|
|
#undef s0len
|
|
#undef s1
|
|
#undef s1sz
|
|
#undef s1len
|
|
#undef s2
|
|
#undef s2sz
|
|
#undef s2len
|
|
#undef s3
|
|
#undef s3sz
|
|
#undef s3len
|
|
#undef s4
|
|
#undef s4sz
|
|
#undef s4len
|
|
#undef s5
|
|
#undef s5sz
|
|
#undef s5len
|
|
|
|
/*
|
|
* copy-pasta from gnu-efi
|
|
*/
|
|
static inline UINTN
|
|
gnuefi_strncmp (
|
|
IN CONST CHAR8 *s1,
|
|
IN CONST CHAR8 *s2,
|
|
IN UINTN len
|
|
)
|
|
{
|
|
while (*s1 && len) {
|
|
if (*s1 != *s2) {
|
|
break;
|
|
}
|
|
|
|
s1 += 1;
|
|
s2 += 1;
|
|
len -= 1;
|
|
}
|
|
|
|
return len ? *s1 - *s2 : 0;
|
|
}
|
|
|
|
/*
|
|
* This is still broken, and fails the test case as written on arm.
|
|
* We no longer use this, so we do not strictly need to run it.
|
|
*/
|
|
#if !defined(__arm__) && !defined(__aarch64__)
|
|
static inline INTN
|
|
gnuefi_signed_strncmp (
|
|
IN CONST CHAR8 *s1,
|
|
IN CONST CHAR8 *s2,
|
|
IN UINTN len
|
|
)
|
|
{
|
|
while (*s1 && len) {
|
|
if (*s1 != *s2) {
|
|
break;
|
|
}
|
|
|
|
s1 += 1;
|
|
s2 += 1;
|
|
len -= 1;
|
|
}
|
|
|
|
return len ? *s1 - *s2 : 0;
|
|
}
|
|
#endif
|
|
|
|
static inline INTN
|
|
gnuefi_good_strncmp (
|
|
IN CONST CHAR8 *s1p,
|
|
IN CONST CHAR8 *s2p,
|
|
IN UINTN len
|
|
)
|
|
{
|
|
CONST UINT8 *s1 = (CONST UINT8 *)s1p;
|
|
CONST UINT8 *s2 = (CONST UINT8 *)s2p;
|
|
|
|
while (*s1 && len) {
|
|
if (*s1 != *s2) {
|
|
break;
|
|
}
|
|
|
|
s1 += 1;
|
|
s2 += 1;
|
|
len -= 1;
|
|
}
|
|
|
|
return len ? *s1 - *s2 : 0;
|
|
}
|
|
|
|
/*
|
|
* these are constants so that the failures are readable if you get
|
|
* it wrong.
|
|
*/
|
|
#define s0 "sbat,"
|
|
#define s0sz 6
|
|
#define s0len 5
|
|
#define s1 "sbat,1,2021030218"
|
|
#define s1sz 18
|
|
#define s1len 17
|
|
#define s2 "sbat,1,20210302"
|
|
#define s2sz 16
|
|
#define s2len 15
|
|
#define s3 "sbat,1,20210303"
|
|
#define s3sz 16
|
|
#define s3len 15
|
|
#define s4 "sbat\314\234\014,"
|
|
#define s4sz 9
|
|
#define s4len 8
|
|
/*
|
|
* same as s4 but with a UTF8 encoding error; one bit is cleared.
|
|
*/
|
|
#define s5 "sbat\314\034\014,"
|
|
#define s5sz 9
|
|
#define s5len 8
|
|
|
|
#define test_strncmp_helper(fn, test_cmp_magnitude, invert_sign_errors, \
|
|
invert_encoding_errors) \
|
|
({ \
|
|
printf("testing %s\n", #fn); \
|
|
int status_ = 0, rc_; \
|
|
\
|
|
rc_ = assert_zero_as_expr(fn(s0, s0, s0len), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
rc_ = assert_zero_as_expr(fn(s0, s0, s0sz), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
\
|
|
rc_ = assert_zero_as_expr(fn(s0, s1, s0len), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (invert_sign_errors) \
|
|
rc_ = assert_positive_as_expr(fn(s0, s1, s0sz), -1, \
|
|
"\n"); \
|
|
else \
|
|
rc_ = assert_negative_as_expr(fn(s0, s1, s0sz), -1, \
|
|
"\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (test_cmp_magnitude) { \
|
|
rc_ = assert_equal_as_expr(fn(s0, s1, s0sz), \
|
|
s0[s0len] - s1[s0len], -1, \
|
|
"expected %d got %d\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
} \
|
|
rc_ = assert_positive_as_expr(fn(s1, s0, s0sz), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (test_cmp_magnitude) { \
|
|
rc_ = assert_equal_as_expr(fn(s1, s0, s0sz), \
|
|
s1[s0len] - s0[s0len], -1, \
|
|
"expected %d got %d\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
} \
|
|
\
|
|
rc_ = assert_positive_as_expr(fn(s1, s2, s1sz), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (test_cmp_magnitude) { \
|
|
rc_ = assert_equal_as_expr(fn(s1, s2, s2sz), \
|
|
s1[s2len] - s2[s2len], -1, \
|
|
"expected %d got %d\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
} \
|
|
rc_ = assert_positive_as_expr(fn(s1, s2, s1len), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (test_cmp_magnitude) { \
|
|
rc_ = assert_equal_as_expr( \
|
|
fn(s1, s2, s2len), \
|
|
s1[s2len - 1] - s2[s2len - 1], -1, \
|
|
"expected %d got %d\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
} \
|
|
if (invert_sign_errors) \
|
|
rc_ = assert_positive_as_expr(fn(s2, s1, s1sz), -1, \
|
|
"\n"); \
|
|
else \
|
|
rc_ = assert_negative_as_expr(fn(s2, s1, s1sz), -1, \
|
|
"\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (test_cmp_magnitude) { \
|
|
rc_ = assert_equal_as_expr(fn(s2, s1, s1sz), \
|
|
s2[s2len] - s1[s2len], -1, \
|
|
"expected %d got %d\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
} \
|
|
\
|
|
rc_ = assert_zero_as_expr(fn(s1, s2, s2len), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
rc_ = assert_positive_as_expr(fn(s1, s2, s2sz), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (test_cmp_magnitude) { \
|
|
rc_ = assert_equal_as_expr(fn(s1, s2, s2sz), \
|
|
s1[s2len] - s2[s2len], -1, \
|
|
"expected %d got %d\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
} \
|
|
\
|
|
if (invert_sign_errors) \
|
|
rc_ = assert_positive_as_expr(fn(s2, s3, s2sz), -1, \
|
|
"\n"); \
|
|
else \
|
|
rc_ = assert_negative_as_expr(fn(s2, s3, s2sz), -1, \
|
|
"\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
if (test_cmp_magnitude) { \
|
|
rc_ = assert_equal_as_expr( \
|
|
fn(s2, s3, s2sz), \
|
|
s2[s2len - 1] - s3[s2len - 1], -1, \
|
|
"expected %d got %d\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
rc_ = assert_equal_as_expr( \
|
|
fn(s2, s3, s2len), \
|
|
s2[s2len - 1] - s3[s2len - 1], -1, \
|
|
"expected %d got %d\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
} \
|
|
if (invert_sign_errors) \
|
|
rc_ = assert_positive_as_expr(fn(s2, s3, s2len), -1, \
|
|
"\n"); \
|
|
else \
|
|
rc_ = assert_negative_as_expr(fn(s2, s3, s2len), -1, \
|
|
"\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
rc_ = assert_zero_as_expr(fn(s2, s3, s2len - 1), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
rc_ = assert_false_as_expr(fn(s1, s2, s2len), -1, "\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
\
|
|
if (invert_encoding_errors) \
|
|
rc_ = assert_negative_as_expr(fn(s4, s5, s4sz), -1, \
|
|
"\n"); \
|
|
else \
|
|
rc_ = assert_positive_as_expr(fn(s4, s5, s4sz), -1, \
|
|
"\n"); \
|
|
status_ = MIN(status_, rc_); \
|
|
\
|
|
if (status_ < 0) \
|
|
printf("%s failed\n", #fn); \
|
|
status_; \
|
|
})
|
|
|
|
static int
|
|
test_strncmp(void)
|
|
{
|
|
int status = 0;
|
|
int rc;
|
|
|
|
/*
|
|
* shim's strncmp
|
|
*/
|
|
rc = test_strncmp_helper(shim_strncmp, true, false, false);
|
|
status = MIN(rc, status);
|
|
|
|
/*
|
|
* libc's strncmp
|
|
*/
|
|
/*
|
|
* Deliberately not testing the difference between these two
|
|
* comparisons for the symbol named "strncmp":
|
|
* strncmp("b", "a", 1)
|
|
* strncmp("c", "a", 1)
|
|
* glibc, shim_strncmp(), and even the gnuefi ones will give you 1
|
|
* and 2, respectively, as will glibc's, but valgrind swaps in its
|
|
* own implementation, in case you're doing something that's both
|
|
* clever and dumb with the result, and it'll return 1 for both of
|
|
* them.
|
|
*/
|
|
rc = test_strncmp_helper(strncmp, false, false, false);
|
|
status = MIN(rc, status);
|
|
|
|
/*
|
|
* gnu-efi's broken strncmpa
|
|
*/
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wtype-limits"
|
|
#pragma GCC diagnostic ignored "-Wsign-compare"
|
|
rc = test_strncmp_helper(gnuefi_strncmp, true, true, false);
|
|
status = MIN(rc, status);
|
|
#pragma GCC diagnostic pop
|
|
|
|
/*
|
|
* This is still broken, and fails the test case as written on arm.
|
|
* We no longer use this, so we do not strictly need to run it.
|
|
*/
|
|
#if !defined(__arm__) && !defined(__aarch64__)
|
|
/*
|
|
* gnu-efi's broken strncmpa with the return type fixed
|
|
*/
|
|
rc = test_strncmp_helper(gnuefi_signed_strncmp, true, false, true);
|
|
status = MIN(rc, status);
|
|
#endif
|
|
|
|
/*
|
|
* gnu-efi's strncmpa with the return type fixed and unsigned
|
|
* comparisons internally
|
|
*/
|
|
rc = test_strncmp_helper(gnuefi_good_strncmp, true, false, false);
|
|
status = MIN(rc, status);
|
|
|
|
return status;
|
|
}
|
|
|
|
#undef s0
|
|
#undef s0sz
|
|
#undef s0len
|
|
#undef s1
|
|
#undef s1sz
|
|
#undef s1len
|
|
#undef s2
|
|
#undef s2sz
|
|
#undef s2len
|
|
#undef s3
|
|
#undef s3sz
|
|
#undef s3len
|
|
#undef s4
|
|
#undef s4sz
|
|
#undef s4len
|
|
#undef s5
|
|
#undef s5sz
|
|
#undef s5len
|
|
|
|
/*
|
|
* Put -Wshadow back how it was
|
|
*/
|
|
#pragma GCC diagnostic pop
|
|
|
|
static int
|
|
test_strchr(void)
|
|
{
|
|
char s0[] = "abcbdbeb\0fbgb";
|
|
|
|
assert_equal_return(strchr(s0, 'a'), s0, -1, "got %p expected %p\n");
|
|
assert_equal_return(strchr(s0, 'b'), &s0[1], -1, "got %p expected %p\n");
|
|
assert_equal_return(strchr(&s0[1], 'b'), &s0[1], -1, "got %p expected %p\n");
|
|
assert_equal_return(strchr(&s0[2], 'b'), &s0[3], -1, "got %p expected %p\n");
|
|
assert_equal_return(strchr(&s0[4], 'b'), &s0[5], -1, "got %p expected %p\n");
|
|
assert_equal_return(strchr(&s0[6], 'b'), &s0[7], -1, "got %p expected %p\n");
|
|
assert_equal_return(strchr(&s0[8], 'b'), NULL, -1, "got %p expected %p\n");
|
|
|
|
assert_equal_return(shim_strchr(s0, 'a'), s0, -1, "got %p expected %p\n");
|
|
assert_equal_return(shim_strchr(s0, 'b'), &s0[1], -1, "got %p expected %p\n");
|
|
assert_equal_return(shim_strchr(&s0[1], 'b'), &s0[1], -1, "got %p expected %p\n");
|
|
assert_equal_return(shim_strchr(&s0[2], 'b'), &s0[3], -1, "got %p expected %p\n");
|
|
assert_equal_return(shim_strchr(&s0[4], 'b'), &s0[5], -1, "got %p expected %p\n");
|
|
assert_equal_return(shim_strchr(&s0[6], 'b'), &s0[7], -1, "got %p expected %p\n");
|
|
assert_equal_return(shim_strchr(&s0[8], 'b'), NULL, -1, "got %p expected %p\n");
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
test_stpcpy(void)
|
|
{
|
|
char s0[] = "0123456789abcdef";
|
|
char s1[] = "xxxxxxxxxxxxxxxx";
|
|
char *s;
|
|
|
|
s0[0xa] = 0;
|
|
assert_equal_return(stpcpy(s1, s0), &s1[0xa], -1, "got %p expected %p\n");
|
|
assert_zero_return(memcmp(s0, s1, 11), -1, "\n");
|
|
assert_zero_return(memcmp(&s1[11], "xxxxx", sizeof("xxxxx")), -1, "\n");
|
|
|
|
memset(s1, 'x', sizeof(s1));
|
|
s1[16] = 0;
|
|
assert_equal_return(shim_stpcpy(s1, s0), &s1[0xa], -1, "got %p expected %p\n");
|
|
assert_zero_return(memcmp(s0, s1, 11), -1, "\n");
|
|
assert_zero_return(memcmp(&s1[11], "xxxxx", sizeof("xxxxx")), -1, "\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
test_strdup(void)
|
|
{
|
|
char s0[] = "0123456789abcdef";
|
|
char *s = NULL;
|
|
|
|
s = strdup(s0);
|
|
assert_equal_goto(strcmp(s0, s), 0, err, "\n");
|
|
free(s);
|
|
|
|
s = shim_strdup(s0);
|
|
assert_equal_goto(strcmp(s0, s), 0, err, "\n");
|
|
free(s);
|
|
|
|
return 0;
|
|
err:
|
|
if (s)
|
|
free(s);
|
|
return -1;
|
|
}
|
|
|
|
static int
|
|
test_strndup(void)
|
|
{
|
|
char s0[] = "0123456789abcdef";
|
|
char *s = NULL;
|
|
|
|
s = strndup(s0, 18);
|
|
assert_equal_goto(strcmp(s0, s), 0, err, "\n");
|
|
free(s);
|
|
s = strndup(s0, 15);
|
|
assert_positive_goto(strcmp(s0, s), err, "\n");
|
|
free(s);
|
|
|
|
s = shim_strndup(s0, 18);
|
|
assert_equal_goto(strcmp(s0, s), 0, err, "\n");
|
|
free(s);
|
|
s = strndup(s0, 15);
|
|
assert_positive_goto(shim_strcmp(s0, s), err, "\n");
|
|
free(s);
|
|
|
|
return 0;
|
|
err:
|
|
if (s)
|
|
free(s);
|
|
return -1;
|
|
}
|
|
|
|
static int
|
|
test_strchrnul_helper(__typeof__(strchrnul) fn)
|
|
{
|
|
const char s0[] = "abcd\0fghi";
|
|
|
|
assert_equal_return(fn(s0, 'a'), &s0[0], -1, "got %p expected %p\n");
|
|
assert_equal_return(fn(s0, 'd'), &s0[3], -1, "got %p expected %p\n");
|
|
assert_equal_return(fn(s0, '\000'), &s0[4], -1, "got %p expected %p\n");
|
|
assert_equal_return(fn(s0, 'i'), &s0[4], -1, "got %p expected %p\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
test_strchrnul(void)
|
|
{
|
|
const char s0[] = "abcd\0fghi";
|
|
|
|
assert_equal_return(test_strchrnul_helper(shim_strchrnul),
|
|
test_strchrnul_helper(strchrnul),
|
|
-1, "got %d expected %d\n");
|
|
|
|
assert_equal_return(strnchrnul(s0, 0, 'b'), &s0[0], -1, "got %p expected %p\n");
|
|
assert_equal_return(strnchrnul(s0, -1, 'b'), &s0[1], 1, "got %p expected %p\n");
|
|
assert_equal_return(strnchrnul(s0, 2, 'b'), &s0[1], -1, "got %p expected %p\n");
|
|
assert_equal_return(strnchrnul(s0, 4, 'f'), &s0[3], -1, "got %p expected %p\n");
|
|
assert_equal_return(strnchrnul(s0, 5, 'f'), &s0[4], -1, "got %p expected %p\n");
|
|
assert_equal_return(strnchrnul(s0, 8, 'f'), &s0[4], -1, "got %p expected %p\n");
|
|
|
|
assert_equal_return(strnchrnul(&s0[4], 1, 'f'), &s0[4], -1, "got %p expected %p\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
test_strrchr(void) {
|
|
char s0[] = "abcbebfb";
|
|
|
|
assert_equal_return(shim_strrchr(s0, '\n'), NULL, -1, "got %p expected %p\n");
|
|
assert_equal_return(strrchr(s0, '\n'), NULL, -1, "got %p expected %p\n");
|
|
assert_equal_return(shim_strrchr(s0, 'b'), &s0[7], -1, "got %p expected %p\n");
|
|
assert_equal_return(strrchr(s0, 'b'), &s0[7], -1, "got %p expected %p\n");
|
|
assert_equal_return(shim_strrchr(s0, 'c'), &s0[2], -1, "got %p expected %p\n");
|
|
assert_equal_return(strrchr(s0, 'c'), &s0[2], -1, "got %p expected %p\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
test_strcpy(void)
|
|
{
|
|
char s0[] = "0123456789abcdef\0000";
|
|
char s1[sizeof(s0)];
|
|
|
|
memset(s1, 0, sizeof(s1));
|
|
assert_equal_return(strcpy(s1, s0), s1, -1, "got %p expected %p\n");
|
|
assert_equal_return(strlen(s0), strlen(s1), -1, "got %d expected %d\n");
|
|
|
|
memset(s1, 0, sizeof(s1));
|
|
assert_equal_return(shim_strcpy(s1, s0), s1, -1, "got %p expected %p\n");
|
|
assert_equal_return(strlen(s0), strlen(s1), -1, "got %d expected %d\n");
|
|
|
|
memset(s1, 0, sizeof(s1));
|
|
assert_equal_return(shim_strcpy(s1, s0), s1, -1, "got %p expected %p\n");
|
|
assert_equal_return(strlen(s0), strlen(s1), -1, "got %d expected %d\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
test_strncpy(void)
|
|
{
|
|
char s[] = "0123456789abcdef\0000";
|
|
char s0[4096];
|
|
char s1[4096];
|
|
|
|
memset(s0, 0, sizeof(s0));
|
|
memcpy(s0, s, sizeof(s));
|
|
#if __GNUC_PREREQ(8, 1)
|
|
# pragma GCC diagnostic push
|
|
# pragma GCC diagnostic ignored "-Wstringop-truncation"
|
|
#endif
|
|
memset(s1, 0, 4096);
|
|
assert_equal_return(strncpy(s1, s0, 0), s1, -1, "got %p expected %p\n");
|
|
assert_equal_return(strlen(s1), 0, -1, "got %d expected %d\n");
|
|
memset(s1, 0, 4096);
|
|
assert_equal_return(shim_strncpy(s1, s0, 0), s1, -1, "got %p expected %p\n");
|
|
assert_equal_return(strlen(s1), 0, -1, "got %d expected %d\n");
|
|
|
|
memset(s1, 0, 4096);
|
|
assert_equal_return(strncpy(s1, s0, 1), s1, -1, "got %p expected %p\n");
|
|
assert_equal_return(strlen(s1), 1, -1, "got %d expected %d\n");
|
|
assert_equal_return(s1[0], s0[0], -1, "got %#02hhx, expected %#02hhx\n");
|
|
assert_equal_return(s0[1], '1', -1, "got %#02hhx, expected %#02hhx\n");
|
|
assert_equal_return(s1[1], '\0', -1, "got %#02hhx, expected %#02hhx\n");
|
|
memset(s1, 0, 4096);
|
|
assert_equal_return(shim_strncpy(s1, s0, 1), s1, -1, "got %p expected %p\n");
|
|
assert_equal_return(strlen(s1), 1, -1, "got %d expected %d\n");
|
|
assert_equal_return(s1[0], s0[0], -1, "got %#02hhx, expected %#02hhx\n");
|
|
assert_equal_return(s0[1], '1', -1, "got %#02hhx, expected %#02hhx\n");
|
|
assert_equal_return(s1[1], '\0', -1, "got %#02hhx, expected %#02hhx\n");
|
|
|
|
memset(s1, 0, 4096);
|
|
assert_equal_return(strncpy(s1, s0, 15), s1, -1, "got %p expected %p\n");
|
|
assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[15], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[17], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[18], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
memset(s1, 0, 4096);
|
|
assert_equal_return(shim_strncpy(s1, s0, 15), s1, -1, "got %p expected %p\n");
|
|
assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[15], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[17], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[18], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
|
|
memset(s1, 0, 4096);
|
|
assert_equal_return(strncpy(s1, s0, 16), s1, -1, "got %p expected %p\n");
|
|
assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[15], 'f', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[17], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[18], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
memset(s1, 0, 4096);
|
|
assert_equal_return(shim_strncpy(s1, s0, 16), s1, -1, "got %p expected %p\n");
|
|
assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[15], 'f', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[17], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[18], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
|
|
memset(s1, 0, 4096);
|
|
s1[17] = '0';
|
|
s1[18] = '1';
|
|
assert_equal_return(strncpy(s1, s0, 4096), s1, -1, "got %p expected %p\n");
|
|
assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[15], 'f', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[17], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[18], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
memset(s1, 0, 4096);
|
|
s1[17] = '0';
|
|
s1[18] = '1';
|
|
assert_equal_return(shim_strncpy(s1, s0, 4096), s1, -1, "got %p expected %p\n");
|
|
assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[15], 'f', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[17], '0', -1, "got %#02hhx expected %02hhx\n");
|
|
assert_equal_return(s1[18], '1', -1, "got %#02hhx expected %02hhx\n");
|
|
#if __GNUC_PREREQ(8, 1)
|
|
# pragma GCC diagnostic pop
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
test_strcat(void)
|
|
{
|
|
char s[] = "0123456789abcdef\0000";
|
|
char s0[4096];
|
|
char s1[4096];
|
|
char *s2;
|
|
char s3[] = "0123456789abcdef0123456789abcdef\000\000\000\000\000";
|
|
|
|
memset(s0, 0, sizeof(s0));
|
|
memcpy(s0, s, sizeof(s));
|
|
|
|
memset(s1, 0, 4096);
|
|
assert_equal_return(strcat(s1, s0), s1, -1, "got %p expected %p\n");
|
|
/* For unknown reasons, gcc 4.8.5 gives us this here:
|
|
* | In file included from shim.h:64:0,
|
|
* | from test-str.c:14:
|
|
* | test-str.c: In function 'test_strcat':
|
|
* | include/test.h:85:10: warning: array subscript is below array bounds [-Warray-bounds]
|
|
* | printf("%s:%d:got %lld, expected zero " fmt, __func__, \
|
|
* | ^
|
|
* | include/test.h:112:10: warning: array subscript is below array bounds [-Warray-bounds]
|
|
* | printf("%s:%d:got %lld, expected < 0 " fmt, __func__, \
|
|
* | ^
|
|
*
|
|
* This clearly isn't a useful error message, as it doesn't tell us
|
|
* /anything about the problem/, but also it isn't reported on
|
|
* later compilers, and it isn't clear that there's any problem
|
|
* when examining these functions.
|
|
*
|
|
* I don't know.
|
|
*/
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Warray-bounds"
|
|
assert_zero_return(strncmp(s1, s0, sizeof(s)-1), 0, -1, "\n");
|
|
assert_negative_return(memcmp(s1, s0, sizeof(s)), 0, -1, "\n");
|
|
#pragma GCC diagnostic pop
|
|
|
|
memset(s1, 0, 4096);
|
|
assert_equal_return(strcat(s1, s0), s1, -1, "got %p expected %p\n");
|
|
s2 = s1 + strlen(s1);
|
|
assert_equal_return(s2, &s1[16], -1, "got %p expected %p\n");
|
|
assert_equal_return(strcat(s2, s0), s2, -1, "got %p expected %p\n");
|
|
assert_zero_return(strncmp(s1, s0, strlen(s)), -1, "got %p expected %p\n");
|
|
assert_zero_return(strncmp(s2, s0, 2*(sizeof(s)-1)), -1, "\n");
|
|
assert_positive_return(memcmp(s1, s0, 2*sizeof(s)-2), -1, "\n");
|
|
assert_equal_return(memcmp(s1, s3, sizeof(s3)), 0, -1, "expected %d got %d\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
test_strntoken_null(void) {
|
|
bool ret;
|
|
char *token = NULL;
|
|
char state;
|
|
|
|
char *delims = alloca(3);
|
|
memcpy(delims, ",.", 3);
|
|
|
|
ret = strntoken(NULL, 1, delims, &token, &state);
|
|
assert_equal_return(ret, false, -1, "got %d expected %d\n");
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
test_strntoken_size_0(void)
|
|
{
|
|
const char s1[] = "abc,def,.,gh,";
|
|
char s2[] = "abc,def,.,gh,";
|
|
char *token = NULL;
|
|
bool ret;
|
|
size_t max;
|
|
char *s = s2;
|
|
size_t tokensz;
|
|
char state;
|
|
|
|
ret = strntoken(s, 0, ",.", &token, &state);
|
|
assert_equal_return(ret, false, -1, "got %d expected %d\n");
|
|
assert_equal_return(token, NULL, -1, "got %p expected %p\n");
|
|
assert_equal_return(memcmp(s, "abc,def,.,gh,", sizeof(s2)), 0, 1, "got %d expected %d\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
test_strntoken_empty_size_1(void)
|
|
{
|
|
char s1[] = "";
|
|
char *s;
|
|
bool ret;
|
|
char *token = NULL;
|
|
char *prevtok = NULL;
|
|
size_t max;
|
|
size_t tokensz;
|
|
char state;
|
|
|
|
s = s1;
|
|
max = 1;
|
|
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, true, -1, "got %d expected %d\n");
|
|
assert_equal_return(token[0], '\0', -1, "got %#hhx expected %#hhx\n");
|
|
prevtok = token;
|
|
|
|
tokensz = strlen(token) + 1;
|
|
s += tokensz;
|
|
max -= tokensz;
|
|
assert_equal_return(s, &s1[1], -1, "got %p expected %p\n");
|
|
assert_equal_return(max, 0, -1, "got %d expected %d\n");
|
|
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, false, -1, "got %d expected %d\n");
|
|
assert_equal_return(token, prevtok, -1, "got %p expected %p\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
test_strntoken_size_1(void)
|
|
{
|
|
char s1[] = ",";
|
|
char *s;
|
|
bool ret;
|
|
char *token = NULL;
|
|
char *prevtok = NULL;
|
|
size_t max;
|
|
size_t tokensz;
|
|
char state;
|
|
|
|
s = s1;
|
|
max = 1;
|
|
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, true, -1, "got %d expected %d\n");
|
|
assert_equal_return(token[0], '\0', -1, "got %#hhx expected %#hhx\n");
|
|
prevtok = token;
|
|
|
|
tokensz = strlen(token) + 1;
|
|
s += tokensz;
|
|
max -= tokensz;
|
|
assert_equal_return(s, &s1[1], -1, "got %p expected %p\n");
|
|
assert_equal_return(max, 0, -1, "got %d expected %d\n");
|
|
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, false, -1, "got %d expected %d\n");
|
|
assert_equal_return(token, prevtok, -1, "got %p expected %p\n");
|
|
assert_equal_return(token[0], '\0', -1, "got %#hhx expected %#hhx\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
test_strntoken_size_2(void)
|
|
{
|
|
char s1[] = ",";
|
|
char *s;
|
|
bool ret;
|
|
char *token = NULL;
|
|
char *prevtok = NULL;
|
|
size_t max;
|
|
size_t tokensz;
|
|
char state;
|
|
|
|
s = s1;
|
|
max = 2;
|
|
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, true, -1, "got %d expected %d\n");
|
|
assert_equal_return(token[0], '\0', -1, "got %#hhx expected %#hhx\n");
|
|
|
|
tokensz = strlen(token) + 1;
|
|
s += tokensz;
|
|
max -= tokensz;
|
|
assert_equal_return(s, &s1[1], -1, "got %p expected %p\n");
|
|
assert_equal_return(max, 1, -1, "got %d expected %d\n");
|
|
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, true, -1, "got %d expected %d\n");
|
|
assert_equal_return(token[0], '\0', -1, "got %#hhx expected %#hhx\n");
|
|
prevtok = token;
|
|
|
|
tokensz = strlen(token) + 1;
|
|
s += tokensz;
|
|
max -= tokensz;
|
|
assert_equal_return(s, &s1[2], -1, "got %p expected %p\n");
|
|
assert_equal_return(max, 0, -1, "got %d expected %d\n");
|
|
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, false, -1, "got %d expected %d\n");
|
|
assert_equal_return(token, prevtok, -1, "got %#hhx expected %#hhx\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
test_strntoken_no_ascii_nul(void)
|
|
{
|
|
const char s1[] = "abc,def,.,gh,";
|
|
char s2[] = "abc,def,.,gh,";
|
|
char *token = NULL;
|
|
bool ret;
|
|
size_t max;
|
|
char *s = s2;
|
|
size_t tokensz;
|
|
char state;
|
|
|
|
s = s2;
|
|
max = sizeof(s2) - 1;
|
|
assert_equal_return(max, 13, -1, "got %d expected %d\n");
|
|
/*
|
|
* s="abc,def,.,gh," -> "abc\0def,.,gh,"
|
|
* ^ token
|
|
*/
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, true, -1, "got %d expected %d\n");
|
|
assert_equal_return(token, s, -1, "got %p expected %p\n");
|
|
assert_equal_return(s[2], 'c', -1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(s[3], '\0', -1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(s[4], 'd', -1, "got %#hhx expected %#hhx\n");
|
|
|
|
tokensz = strnlen(token, max) + 1;
|
|
s += tokensz;
|
|
max -= tokensz;
|
|
assert_equal_return(max, 9, -1, "got %d expected %d\n");
|
|
|
|
/*
|
|
* s="def,.,gh," -> "def\0.,gh,"
|
|
* ^ token
|
|
*/
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, true, -1, "got %d expected %d\n");
|
|
assert_equal_return(token, s, -1, "got %p expected %p\n");
|
|
assert_equal_return(s[2], 'f', -1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(s[3], '\0', -1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(s[4], '.', -1, "got %#hhx expected %#hhx\n");
|
|
|
|
tokensz = strnlen(token, max) + 1;
|
|
s += tokensz;
|
|
max -= tokensz;
|
|
assert_equal_return(max, 5, -1, "got %d expected %d\n");
|
|
|
|
/*
|
|
* s=".,gh," -> "\0,gh,"
|
|
* ^ token
|
|
*/
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, true, -1, "got %d expected %d\n");
|
|
assert_equal_return(token, s, -1, "got %p expected %p\n");
|
|
assert_equal_return(s[0], '\0', -1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(s[1], ',', -1, "got %#hhx expected %#hhx\n");
|
|
|
|
tokensz = strnlen(token, max) + 1;
|
|
s += tokensz;
|
|
max -= tokensz;
|
|
assert_equal_return(max, 4, -1, "got %d expected %d\n");
|
|
|
|
/*
|
|
* s=",gh," -> "\0gh,"
|
|
* ^ token
|
|
*/
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, true, -1, "got %d expected %d\n");
|
|
assert_equal_return(token, s, -1, "got %p expected %p\n");
|
|
assert_equal_return(s[0], '\0', -1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(s[1], 'g', -1, "got %#hhx expected %#hhx\n");
|
|
|
|
tokensz = strnlen(token, max) + 1;
|
|
s += tokensz;
|
|
max -= tokensz;
|
|
assert_equal_return(max, 3, -1, "got %d expected %d\n");
|
|
|
|
/*
|
|
* s="gh," -> "gh\0"
|
|
* ^ token
|
|
*/
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, true, -1, "got %d expected %d\n");
|
|
assert_equal_return(token, s, -1, "got %p expected %p\n");
|
|
assert_equal_return(s[0], 'g', -1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(s[1], 'h', -1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(s[2], '\0', -1, "got %#hhx expected %#hhx\n");
|
|
|
|
tokensz = strnlen(token, max) + 1;
|
|
s += tokensz;
|
|
max -= tokensz;
|
|
assert_equal_return(max, 0, -1, "got %d expected %d\n");
|
|
|
|
char *prevtok = token;
|
|
|
|
/*
|
|
* s="" -> ""
|
|
* ^ token, but max is 0
|
|
*/
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, false, -1, "got %d expected %d\n");
|
|
assert_equal_return(token, prevtok, -1, "got %p expected %p\n");
|
|
assert_equal_return(s[0], '\0', -1, "got %#hhx expected %#hhx\n");
|
|
|
|
s[0] = 'x';
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, false, -1, "got %d expected %d\n");
|
|
assert_equal_return(token, prevtok, -1, "got %p expected %p\n");
|
|
assert_equal_return(s[0], 'x', -1, "got %#hhx expected %#hhx\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
test_strntoken_with_ascii_nul(void)
|
|
{
|
|
const char s1[] = "abc,def,.,gh,";
|
|
char s2[] = "abc,def,.,gh,";
|
|
char *token = NULL;
|
|
bool ret;
|
|
size_t max;
|
|
char *s = s2;
|
|
size_t tokensz;
|
|
char s3[] = "abc,def,.,gh,";
|
|
char state;
|
|
|
|
s = s2;
|
|
max = sizeof(s2);
|
|
assert_equal_return(max, 14, 1, "got %d expected %d\n");
|
|
/*
|
|
* s="abc,def,.,gh," -> "abc\0def,.,gh,"
|
|
* ^ token
|
|
*/
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, true, 1, "got %d expected %d\n");
|
|
assert_equal_return(s[2], 'c', 1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(s[3], '\0', 1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(s[4], 'd', 1, "got %#hhx expected %#hhx\n");
|
|
|
|
tokensz = strnlen(token, max) + 1;
|
|
s += tokensz;
|
|
max -= tokensz;
|
|
assert_equal_return(max, 10, 1, "got %d expected %d\n");
|
|
|
|
/*
|
|
* s="def,.,gh," -> "def\0.,gh,"
|
|
* ^ token
|
|
*/
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, true, 1, "got %d expected %d\n");
|
|
assert_equal_return(token, s, 1, "got %p expected %p\n");
|
|
assert_equal_return(s[2], 'f', 1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(s[3], '\0', 1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(s[4], '.', 1, "got %#hhx expected %#hhx\n");
|
|
|
|
tokensz = strnlen(token, max) + 1;
|
|
s += tokensz;
|
|
max -= tokensz;
|
|
assert_equal_return(max, 6, 1, "got %d expected %d\n");
|
|
|
|
/*
|
|
* s=".,gh," -> "\0,gh,"
|
|
* ^ token
|
|
*/
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, true, 1, "got %d expected %d\n");
|
|
assert_equal_return(token, s, 1, "got %p expected %p\n");
|
|
assert_equal_return(s[0], '\0', 1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(s[1], ',', 1, "got %#hhx expected %#hhx\n");
|
|
|
|
tokensz = strnlen(token, max) + 1;
|
|
s += tokensz;
|
|
max -= tokensz;
|
|
assert_equal_return(max, 5, 1, "got %d expected %d\n");
|
|
|
|
/*
|
|
* s=",gh," -> "\0gh,"
|
|
* ^ token
|
|
*/
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, true, 1, "got %d expected %d\n");
|
|
assert_equal_return(token, s, 1, "got %p expected %p\n");
|
|
assert_equal_return(s[0], '\0', 1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(s[1], 'g', 1, "got %#hhx expected %#hhx\n");
|
|
|
|
tokensz = strnlen(token, max) + 1;
|
|
s += tokensz;
|
|
max -= tokensz;
|
|
assert_equal_return(max, 4, 1, "got %d expected %d\n");
|
|
|
|
/*
|
|
* s="gh," -> "gh\0"
|
|
* ^ token
|
|
*/
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, true, 1, "got %d expected %d\n");
|
|
assert_equal_return(token, s, 1, "got %p expected %p\n");
|
|
assert_equal_return(s[0], 'g', 1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(s[1], 'h', 1, "got %#hhx expected %#hhx\n");
|
|
assert_equal_return(s[2], '\0', 1, "got %#hhx expected %#hhx\n");
|
|
|
|
tokensz = strnlen(token, max) + 1;
|
|
s += tokensz;
|
|
max -= tokensz;
|
|
assert_equal_return(max, 1, 1, "got %d expected %d\n");
|
|
|
|
/*
|
|
* s="" -> ""
|
|
* ^ token, max is 1
|
|
*/
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, true, 1, "got %d expected %d\n");
|
|
assert_equal_return(token, s, 1, "got %p expected %p\n");
|
|
assert_equal_return(s[0], '\0', 1, "got %#hhx expected %#hhx\n");
|
|
|
|
char *prevtok = token;
|
|
tokensz = strnlen(token, max) + 1;
|
|
s += tokensz;
|
|
max -= tokensz;
|
|
assert_equal_return(max, 0, 1, "got %d expected %d\n");
|
|
|
|
/*
|
|
* s="" -> ""
|
|
* ^ token, max is 0
|
|
*/
|
|
ret = strntoken(s, max, ",.", &token, &state);
|
|
assert_equal_return(ret, false, 1, "got %d expected %d\n");
|
|
assert_equal_return(token, prevtok, 1, "got %p expected %p\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
int status = 0;
|
|
test(test_strlen);
|
|
test(test_strnlen);
|
|
test(test_strcmp);
|
|
test(test_strncmp);
|
|
test(test_strcasecmp);
|
|
test(test_strncasecmp);
|
|
test(test_strrchr);
|
|
test(test_strcpy);
|
|
test(test_strncpy);
|
|
test(test_strcat);
|
|
test(test_stpcpy);
|
|
test(test_strdup);
|
|
test(test_strndup);
|
|
test(test_strchr);
|
|
test(test_strchrnul);
|
|
test(test_strntoken_null);
|
|
test(test_strntoken_size_0);
|
|
test(test_strntoken_empty_size_1);
|
|
test(test_strntoken_size_1);
|
|
test(test_strntoken_size_2);
|
|
test(test_strntoken_no_ascii_nul);
|
|
test(test_strntoken_with_ascii_nul);
|
|
return status;
|
|
}
|
|
|
|
// vim:fenc=utf-8:tw=75:noet
|