From 1fb95511fd6a778293f43d15bacacec9d85b2f92 Mon Sep 17 00:00:00 2001 From: Craig Comstock Date: Tue, 23 Jun 2026 14:34:08 -0500 Subject: [PATCH 1/3] Fixed StringSubstring() case where one or zero characters should be returned Test cases added. Ticket: none Changelog: none --- libutils/string_lib.c | 2 +- tests/unit/string_lib_test.c | 43 ++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/libutils/string_lib.c b/libutils/string_lib.c index 9de4f969..248e893f 100644 --- a/libutils/string_lib.c +++ b/libutils/string_lib.c @@ -418,7 +418,7 @@ char *StringSubstring(const char *source, size_t source_len, int start, int len) start = source_len + start; } - if (start >= end) + if (start > end) { return NULL; } diff --git a/tests/unit/string_lib_test.c b/tests/unit/string_lib_test.c index 7386d743..00d10d81 100644 --- a/tests/unit/string_lib_test.c +++ b/tests/unit/string_lib_test.c @@ -369,6 +369,47 @@ static void test_substring_overshoot(void) free(new_string); } +static void test_substring_result_is_one_char(void) +{ + { + char *new_string = StringSubstring("[1]", 3, 1, -1); + assert_string_equal(new_string, "1"); + free(new_string); + } + { + char *new_string = StringSubstring("[1]", 3, 0, 1); + assert_string_equal(new_string, "["); + free(new_string); + } + { + char *new_string = StringSubstring("[1]", 3, 2, 1); + assert_string_equal(new_string, "]"); + free(new_string); + } + { + char *new_string = StringSubstring("1", 1, 0, 1); + assert_string_equal(new_string, "1"); + free(new_string); + } + { + char *new_string = StringSubstring("1", 1, 0, -1); + assert_string_equal(new_string, "1"); + free(new_string); + } + { + char *new_string = StringSubstring("1", 1, 0, 0); + assert_string_equal(new_string, ""); + free(new_string); + } +} + +static void test_substring_empty_input(void) +{ + char *new_string = StringSubstring("", 0, 0, 1); + assert_string_equal(new_string, ""); + free(new_string); +} + static void test_substring_positive(void) { char *new_string = StringSubstring("abcdef", 6, 2, 3); @@ -1568,6 +1609,8 @@ int main() unit_test(test_concatenate), unit_test(test_substring_overshoot), + unit_test(test_substring_result_is_one_char), + unit_test(test_substring_empty_input), unit_test(test_substring_positive), unit_test(test_substring_negative_length), unit_test(test_substring_negative), From 01977fbb4fc7239e193746664b7938892ca6b2a7 Mon Sep 17 00:00:00 2001 From: Craig Comstock Date: Tue, 23 Jun 2026 14:35:06 -0500 Subject: [PATCH 2/3] Adjusted json.c HexStringToChar() to avoid gnu-folded-constant warning for non-portable VLA usage variable lengh arrays are supported in C99 and optional in C11 but can cause portability issues, so prefer to use alloca() to allocate on the stack frame which is automatically freed when the function returns. Was breaking macos unit test workflow. Ticket: none Changelog: none --- libutils/json.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libutils/json.c b/libutils/json.c index f54d4ca1..42f41263 100644 --- a/libutils/json.c +++ b/libutils/json.c @@ -1043,7 +1043,8 @@ static bool HexStringToChar(const char *hex_string, char *res) return false; } - char tmp[hex_len + 1]; + char *tmp; + tmp = alloca(hex_len + 1); memcpy(tmp, hex_string, hex_len); tmp[hex_len] = '\0'; From 8cbd0dbed19a9c1fb08169b306dcaa487ac520e2 Mon Sep 17 00:00:00 2001 From: Craig Comstock Date: Tue, 23 Jun 2026 16:19:52 -0500 Subject: [PATCH 3/3] Adjusted expectations in one case where end is less than start, used to return NULL, now returns empty string which aligns e.g. with python array[1:-5] results --- libutils/string_lib.c | 2 +- tests/unit/string_lib_test.c | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/libutils/string_lib.c b/libutils/string_lib.c index 248e893f..5bf3c79c 100644 --- a/libutils/string_lib.c +++ b/libutils/string_lib.c @@ -420,7 +420,7 @@ char *StringSubstring(const char *source, size_t source_len, int start, int len) if (start > end) { - return NULL; + return SafeStringDuplicate(""); } char *result = xcalloc(end - start + 2, sizeof(char)); diff --git a/tests/unit/string_lib_test.c b/tests/unit/string_lib_test.c index 00d10d81..be5866c8 100644 --- a/tests/unit/string_lib_test.c +++ b/tests/unit/string_lib_test.c @@ -410,6 +410,14 @@ static void test_substring_empty_input(void) free(new_string); } +static void test_substring_empty_output(void) +{ + char *new_string = StringSubstring("\"\"", 2, 1, -1); + assert_string_equal(new_string, ""); + free(new_string); +} + + static void test_substring_positive(void) { char *new_string = StringSubstring("abcdef", 6, 2, 3); @@ -437,8 +445,9 @@ static void test_substring_negative(void) static void test_substring_evil(void) { char *new_string = StringSubstring("abcdef", 6, 4, -4); + assert_string_equal(new_string, ""); + free(new_string); - assert_int_equal(new_string, NULL); } static void test_string_to_long(void) @@ -1611,6 +1620,7 @@ int main() unit_test(test_substring_overshoot), unit_test(test_substring_result_is_one_char), unit_test(test_substring_empty_input), + unit_test(test_substring_empty_output), unit_test(test_substring_positive), unit_test(test_substring_negative_length), unit_test(test_substring_negative),