mirror of https://github.com/wolfSSL/wolfBoot.git
Fix strncasecmp bounds and alpha-only case folding
+ Added unit tests for string.cpull/691/head
parent
0a738ac4d1
commit
25ae592093
13
src/string.c
13
src/string.c
|
|
@ -117,6 +117,11 @@ int strcmp(const char *s1, const char *s2)
|
|||
}
|
||||
#endif /* Renesas CCRX */
|
||||
|
||||
static int is_alpha(int c)
|
||||
{
|
||||
return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
|
||||
}
|
||||
|
||||
int strcasecmp(const char *s1, const char *s2)
|
||||
{
|
||||
int diff = 0;
|
||||
|
|
@ -124,7 +129,8 @@ int strcasecmp(const char *s1, const char *s2)
|
|||
while (!diff && *s1) {
|
||||
diff = (int)*s1 - (int)*s2;
|
||||
|
||||
if ((diff == 'A' - 'a') || (diff == 'a' - 'A'))
|
||||
if (((diff == 'A' - 'a') || (diff == 'a' - 'A')) &&
|
||||
(is_alpha((unsigned char)*s1) || is_alpha((unsigned char)*s2)))
|
||||
diff = 0;
|
||||
|
||||
s1++;
|
||||
|
|
@ -142,12 +148,13 @@ int strncasecmp(const char *s1, const char *s2, size_t n)
|
|||
while (!diff && *s1) {
|
||||
diff = (int)*s1 - (int)*s2;
|
||||
|
||||
if ((diff == 'A' - 'a') || (diff == 'a' - 'A'))
|
||||
if (((diff == 'A' - 'a') || (diff == 'a' - 'A')) &&
|
||||
(is_alpha((unsigned char)*s1) || is_alpha((unsigned char)*s2)))
|
||||
diff = 0;
|
||||
|
||||
s1++;
|
||||
s2++;
|
||||
if (++i > n)
|
||||
if (++i >= n)
|
||||
break;
|
||||
}
|
||||
return diff;
|
||||
|
|
|
|||
|
|
@ -25,10 +25,11 @@ LDFLAGS+=-ftest-coverage
|
|||
|
||||
|
||||
|
||||
TESTS:=unit-parser unit-extflash unit-spi-flash unit-aes128 unit-aes256 \
|
||||
unit-chacha20 unit-pci unit-mock-state unit-sectorflags unit-image \
|
||||
unit-nvm unit-nvm-flagshome unit-enc-nvm unit-enc-nvm-flagshome \
|
||||
unit-delta unit-update-flash unit-update-ram unit-pkcs11_store
|
||||
TESTS:=unit-parser unit-extflash unit-string unit-spi-flash unit-aes128 \
|
||||
unit-aes256 unit-chacha20 unit-pci unit-mock-state unit-sectorflags \
|
||||
unit-image unit-nvm unit-nvm-flagshome unit-enc-nvm \
|
||||
unit-enc-nvm-flagshome unit-delta unit-update-flash unit-update-ram \
|
||||
unit-pkcs11_store
|
||||
|
||||
all: $(TESTS)
|
||||
|
||||
|
|
@ -94,6 +95,9 @@ unit-extflash: ../../include/target.h unit-extflash.c
|
|||
unit-spi-flash: ../../include/target.h unit-spi-flash.c
|
||||
gcc -o $@ $^ $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
unit-string: ../../include/target.h unit-string.c
|
||||
gcc -o $@ $^ $(CFLAGS) -DDEBUG_UART -DPRINTF_ENABLED $(LDFLAGS)
|
||||
|
||||
unit-aes128: ../../include/target.h unit-extflash.c
|
||||
gcc -o $@ $^ $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,358 @@
|
|||
/* unit-string.c
|
||||
*
|
||||
* Unit tests for string.c.
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2025 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
*
|
||||
* wolfBoot is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfBoot is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
#define FAST_MEMCPY
|
||||
#define DEBUG_UART
|
||||
#define PRINTF_ENABLED
|
||||
|
||||
#include <check.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "string.c"
|
||||
|
||||
static char uart_buf[256];
|
||||
static size_t uart_len;
|
||||
|
||||
void uart_write(const char* buf, unsigned int sz)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < sz && uart_len + 1 < sizeof(uart_buf); i++) {
|
||||
uart_buf[uart_len++] = buf[i];
|
||||
}
|
||||
uart_buf[uart_len] = '\0';
|
||||
}
|
||||
|
||||
static void reset_uart_buf(void)
|
||||
{
|
||||
memset(uart_buf, 0, sizeof(uart_buf));
|
||||
uart_len = 0;
|
||||
}
|
||||
|
||||
START_TEST(test_strncasecmp_n_zero)
|
||||
{
|
||||
ck_assert_int_eq(strncasecmp("ABC", "abc", 0), 0);
|
||||
ck_assert_int_eq(strncasecmp("A", "B", 0), 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_strncasecmp_n_one)
|
||||
{
|
||||
ck_assert_int_eq(strncasecmp("A", "a", 1), 0);
|
||||
ck_assert_int_lt(strncasecmp("A", "b", 1), 0);
|
||||
ck_assert_int_gt(strncasecmp("b", "A", 1), 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_strncasecmp_n_exact)
|
||||
{
|
||||
ck_assert_int_eq(strncasecmp("AbC", "aBc", 3), 0);
|
||||
ck_assert_int_eq(strncasecmp("AbCd", "aBcE", 3), 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_strncasecmp_diff_before_n)
|
||||
{
|
||||
ck_assert_int_lt(strncasecmp("abc", "abd", 3), 0);
|
||||
ck_assert_int_gt(strncasecmp("abd", "abc", 3), 0);
|
||||
ck_assert_int_lt(strncasecmp("", "a", 1), 0);
|
||||
ck_assert_int_eq(strncasecmp("", "a", 0), 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_case_insensitive_alpha_only)
|
||||
{
|
||||
ck_assert_int_ne(strcasecmp("@", "`"), 0);
|
||||
ck_assert_int_ne(strcasecmp("[", "{"), 0);
|
||||
ck_assert_int_ne(strcasecmp("]", "}"), 0);
|
||||
ck_assert_int_ne(strncasecmp("@", "`", 1), 0);
|
||||
ck_assert_int_ne(strcasecmp("a@", "A`"), 0);
|
||||
ck_assert_int_ne(strncasecmp("a@", "A`", 2), 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_isalpha_helpers)
|
||||
{
|
||||
ck_assert_int_eq(islower('a'), 1);
|
||||
ck_assert_int_eq(islower('Z'), 0);
|
||||
ck_assert_int_eq(isupper('Z'), 1);
|
||||
ck_assert_int_eq(isupper('a'), 0);
|
||||
ck_assert_int_eq(isalpha('Q'), 1);
|
||||
ck_assert_int_eq(isalpha('q'), 1);
|
||||
ck_assert_int_eq(isalpha('1'), 0);
|
||||
ck_assert_int_eq(tolower('A'), 'a');
|
||||
ck_assert_int_eq(tolower('a'), 'a');
|
||||
ck_assert_int_eq(toupper('a'), 'A');
|
||||
ck_assert_int_eq(toupper('A'), 'A');
|
||||
ck_assert_int_eq(tolower('1'), '1');
|
||||
ck_assert_int_eq(toupper('1'), '1');
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_memset_memcmp_memchr)
|
||||
{
|
||||
uint8_t buf[8];
|
||||
uint8_t other[8];
|
||||
|
||||
memset(buf, 0xAA, sizeof(buf));
|
||||
memset(other, 0xAA, sizeof(other));
|
||||
ck_assert_int_eq(memcmp(buf, other, sizeof(buf)), 0);
|
||||
|
||||
other[3] = 0xAB;
|
||||
ck_assert_int_lt(memcmp(buf, other, sizeof(buf)), 0);
|
||||
ck_assert_int_eq(memcmp(buf, other, 0), 0);
|
||||
|
||||
ck_assert_ptr_eq(memchr(buf, 0xAA, sizeof(buf)), &buf[0]);
|
||||
ck_assert_ptr_eq(memchr(buf, 0xAB, sizeof(buf)), NULL);
|
||||
buf[6] = 0xAA;
|
||||
ck_assert_ptr_eq(memchr(buf, 0xAA, 8), &buf[0]);
|
||||
ck_assert_ptr_eq(memchr(buf, 0xAA, 1), &buf[0]);
|
||||
ck_assert_ptr_eq(memchr(buf, 0xAA, 0), NULL);
|
||||
ck_assert_ptr_eq(memchr(buf, 0xAA, 7), &buf[0]);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_strlen_strcmp)
|
||||
{
|
||||
ck_assert_uint_eq(strlen(""), 0);
|
||||
ck_assert_uint_eq(strlen("abc"), 3);
|
||||
ck_assert_int_eq(strcmp("abc", "abc"), 0);
|
||||
ck_assert_int_lt(strcmp("abc", "abd"), 0);
|
||||
ck_assert_int_gt(strcmp("abe", "abd"), 0);
|
||||
ck_assert_int_lt(strcmp("", "a"), 0);
|
||||
ck_assert_int_gt(strcmp("a", ""), 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_strcpy_strncpy_strcat_strncat)
|
||||
{
|
||||
char buf[8];
|
||||
char dest[8];
|
||||
char short_dest[4];
|
||||
|
||||
strcpy(buf, "hi");
|
||||
ck_assert_str_eq(buf, "hi");
|
||||
|
||||
memset(dest, 0, sizeof(dest));
|
||||
strncpy(dest, "abc", 4);
|
||||
ck_assert_str_eq(dest, "abc");
|
||||
|
||||
memset(short_dest, 'X', sizeof(short_dest));
|
||||
strncpy(short_dest, "abcdef", 3);
|
||||
ck_assert_int_eq(short_dest[0], 'a');
|
||||
ck_assert_int_eq(short_dest[1], 'b');
|
||||
ck_assert_int_eq(short_dest[2], 'c');
|
||||
ck_assert_int_eq(short_dest[3], 'X');
|
||||
|
||||
strcpy(dest, "a");
|
||||
strcat(dest, "b");
|
||||
ck_assert_str_eq(dest, "ab");
|
||||
|
||||
strcpy(dest, "a");
|
||||
strncat(dest, "bc", 3);
|
||||
ck_assert_str_eq(dest, "ab");
|
||||
|
||||
strcpy(dest, "a");
|
||||
strncat(dest, "bc", 1);
|
||||
ck_assert_str_eq(dest, "a");
|
||||
|
||||
strcpy(dest, "");
|
||||
strncat(dest, "x", 2);
|
||||
ck_assert_str_eq(dest, "x");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_strncmp)
|
||||
{
|
||||
ck_assert_int_eq(strncmp("abc", "abc", 3), 0);
|
||||
ck_assert_int_lt(strncmp("abc", "abd", 3), 0);
|
||||
ck_assert_int_eq(strncmp("abc", "abd", 2), 0);
|
||||
ck_assert_int_eq(strncmp("abc", "abc", 0), 0);
|
||||
ck_assert_int_lt(strncmp("", "a", 1), 0);
|
||||
ck_assert_int_gt(strncmp("a", "", 1), 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_memcpy_memmove)
|
||||
{
|
||||
union {
|
||||
unsigned long align;
|
||||
unsigned char buf[32];
|
||||
} storage;
|
||||
unsigned char src[16];
|
||||
unsigned char dst[16];
|
||||
unsigned char *p = (unsigned char *)&storage.align;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
src[i] = (unsigned char)i;
|
||||
dst[i] = 0;
|
||||
p[i] = (unsigned char)i;
|
||||
}
|
||||
|
||||
memcpy(dst, src, 16);
|
||||
ck_assert_int_eq(memcmp(src, dst, 16), 0);
|
||||
|
||||
memmove(p + 2, p, 8);
|
||||
ck_assert_int_eq(p[2], 0);
|
||||
ck_assert_int_eq(p[3], 1);
|
||||
|
||||
memmove(p, p + 2, 8);
|
||||
ck_assert_int_eq(p[0], 0);
|
||||
ck_assert_int_eq(p[1], 1);
|
||||
|
||||
ck_assert_ptr_eq(memmove(p, p, 4), p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_memcpy_fastpath_aligned)
|
||||
{
|
||||
union {
|
||||
unsigned long align;
|
||||
unsigned char buf[64];
|
||||
} storage;
|
||||
unsigned char *src = (unsigned char *)&storage.align;
|
||||
unsigned char *dst = src + 16;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
src[i] = (unsigned char)(i + 1);
|
||||
dst[i] = 0;
|
||||
}
|
||||
|
||||
memcpy(dst, src, 32);
|
||||
ck_assert_int_eq(memcmp(src, dst, 32), 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_uart_writenum_basic)
|
||||
{
|
||||
reset_uart_buf();
|
||||
uart_writenum(0, 10, 0, 0);
|
||||
ck_assert_str_eq(uart_buf, "0");
|
||||
|
||||
reset_uart_buf();
|
||||
uart_writenum(255, 16, 0, 0);
|
||||
ck_assert_str_eq(uart_buf, "FF");
|
||||
|
||||
reset_uart_buf();
|
||||
uart_writenum(-5, 10, 0, 0);
|
||||
ck_assert_str_eq(uart_buf, "-5");
|
||||
|
||||
reset_uart_buf();
|
||||
uart_writenum(7, 10, 1, 4);
|
||||
ck_assert_str_eq(uart_buf, "0007");
|
||||
|
||||
reset_uart_buf();
|
||||
uart_writenum(1, 10, 1, 2);
|
||||
ck_assert_str_eq(uart_buf, "01");
|
||||
|
||||
reset_uart_buf();
|
||||
uart_writenum(0x1234, 16, 1, 6);
|
||||
ck_assert_str_eq(uart_buf, "001234");
|
||||
|
||||
reset_uart_buf();
|
||||
uart_writenum(1, 10, 1, 64);
|
||||
ck_assert_int_eq(uart_buf[0], '0');
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_uart_printf_formats)
|
||||
{
|
||||
reset_uart_buf();
|
||||
uart_printf("X=%u Y=%d Z=%x W=%X %% %s %c", 5U, -3, 0x2a, 0x2a, "ok", '!');
|
||||
ck_assert_str_eq(uart_buf, "X=5 Y=-3 Z=2A W=2A % ok !");
|
||||
|
||||
reset_uart_buf();
|
||||
uart_printf("%04u", 12U);
|
||||
ck_assert_str_eq(uart_buf, "0012");
|
||||
|
||||
reset_uart_buf();
|
||||
uart_printf("%p", (void*)0x10);
|
||||
ck_assert_str_eq(uart_buf, "0x10");
|
||||
|
||||
reset_uart_buf();
|
||||
uart_printf("A%08uB", 12U);
|
||||
ck_assert_str_eq(uart_buf, "A00000012B");
|
||||
|
||||
reset_uart_buf();
|
||||
uart_printf("%12u", 3U);
|
||||
ck_assert_str_eq(uart_buf, "3");
|
||||
|
||||
reset_uart_buf();
|
||||
uart_printf("%lu", (unsigned long)7);
|
||||
ck_assert_str_eq(uart_buf, "7");
|
||||
|
||||
reset_uart_buf();
|
||||
uart_printf("%zu", (size_t)9);
|
||||
ck_assert_str_eq(uart_buf, "9");
|
||||
|
||||
reset_uart_buf();
|
||||
uart_printf("bad%qend");
|
||||
ck_assert_str_eq(uart_buf, "badend");
|
||||
|
||||
reset_uart_buf();
|
||||
uart_printf("%i", -1);
|
||||
ck_assert_str_eq(uart_buf, "-1");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *string_suite(void)
|
||||
{
|
||||
Suite *s = suite_create("String");
|
||||
TCase *tcase_strncasecmp = tcase_create("strncasecmp");
|
||||
TCase *tcase_misc = tcase_create("misc");
|
||||
|
||||
tcase_add_test(tcase_strncasecmp, test_strncasecmp_n_zero);
|
||||
tcase_add_test(tcase_strncasecmp, test_strncasecmp_n_one);
|
||||
tcase_add_test(tcase_strncasecmp, test_strncasecmp_n_exact);
|
||||
tcase_add_test(tcase_strncasecmp, test_strncasecmp_diff_before_n);
|
||||
tcase_add_test(tcase_strncasecmp, test_case_insensitive_alpha_only);
|
||||
tcase_add_test(tcase_misc, test_isalpha_helpers);
|
||||
tcase_add_test(tcase_misc, test_memset_memcmp_memchr);
|
||||
tcase_add_test(tcase_misc, test_strlen_strcmp);
|
||||
tcase_add_test(tcase_misc, test_strcpy_strncpy_strcat_strncat);
|
||||
tcase_add_test(tcase_misc, test_strncmp);
|
||||
tcase_add_test(tcase_misc, test_memcpy_memmove);
|
||||
tcase_add_test(tcase_misc, test_uart_writenum_basic);
|
||||
tcase_add_test(tcase_misc, test_uart_printf_formats);
|
||||
|
||||
suite_add_tcase(s, tcase_strncasecmp);
|
||||
suite_add_tcase(s, tcase_misc);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int fails;
|
||||
Suite *s = string_suite();
|
||||
SRunner *sr = srunner_create(s);
|
||||
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
fails = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
|
||||
return fails;
|
||||
}
|
||||
Loading…
Reference in New Issue