From ea4b8c38c31467cba2f3543759904f2332de8631 Mon Sep 17 00:00:00 2001 From: yi chen <94xhn1@gmail.com> Date: Sat, 18 Jul 2026 03:45:52 +0800 Subject: [PATCH] fix(string): avoid empty-pattern loop An empty search pattern never advances either strstr loop. Treat it as a successful no-op, matching the existing no-match behavior. Confidence: high Scope-risk: narrow Tested: official sc_str CMake test with ASan; GCC 13 ASan/UBSan; MinGW GCC 8 Not-tested: MSVC --- string/sc_str.c | 4 ++++ string/str_test.c | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/string/sc_str.c b/string/sc_str.c index 4d378b9..6b2a8bc 100644 --- a/string/sc_str.c +++ b/string/sc_str.c @@ -367,6 +367,10 @@ bool sc_str_replace(char **str, const char *replace, const char *with) rep_len = strlen(replace); with_len = strlen(with); + if (rep_len == 0) { + return true; + } + if (rep_len >= UINT32_MAX || with_len >= UINT32_MAX) { return false; } diff --git a/string/str_test.c b/string/str_test.c index 6cbf12b..5b1cbfb 100644 --- a/string/str_test.c +++ b/string/str_test.c @@ -459,6 +459,11 @@ void test5(void) assert(strcmp(s1, "longeRlongeR") == 0); assert(sc_str_replace(&s1, "longeR", "")); assert(strcmp(s1, "") == 0); + sc_str_set(&s1, "unchanged"); + assert(sc_str_replace(&s1, "", "x")); + assert(strcmp(s1, "unchanged") == 0); + assert(sc_str_replace(&s1, "", "")); + assert(strcmp(s1, "unchanged") == 0); sc_str_destroy(&s1); s1 = sc_str_create("*test * test*");