From: Chris Down Date: Sat, 14 Feb 2026 16:40:14 +0000 (+0800) Subject: string-util: Prevent infinite loop pegging CPU on malformed ESC input X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0a664310311b9b2abc79978eb4427c36268c1296;p=thirdparty%2Fsystemd.git string-util: Prevent infinite loop pegging CPU on malformed ESC input string_has_ansi_sequence() currently does this to look for ESC input: t = memchr(s, 0x1B, ...) So each iteration re-searches from the original start pointer. But if we find an ESC byte that does *not* start a valid ANSI sequence (like "\x1B ", or an ESC at the end of the string), then ansi_sequence_length() returns 0, and if that ESC is still in the search window, we will just spin consuming 100% CPU forever. Fix this by always advancing past rejected ESC bytes. --- diff --git a/src/basic/string-util.c b/src/basic/string-util.c index ecd0277577d..055e571afb6 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -267,9 +267,11 @@ static size_t ansi_sequence_length(const char *s, size_t len) { static bool string_has_ansi_sequence(const char *s, size_t len) { const char *t = s; - while ((t = memchr(s, 0x1B, len - (t - s)))) + while ((t = memchr(t, 0x1B, len - (t - s)))) { if (ansi_sequence_length(t, len - (t - s)) > 0) return true; + t++; + } return false; } diff --git a/src/test/test-ellipsize.c b/src/test/test-ellipsize.c index 83978446e18..2efb123ac2b 100644 --- a/src/test/test-ellipsize.c +++ b/src/test/test-ellipsize.c @@ -156,4 +156,14 @@ TEST(ellipsize_ansi_cats) { ASSERT_STREQ(h, "🐱…" ANSI_NORMAL "🐱" ANSI_NORMAL); } +TEST(ellipsize_esc_infinite_loop) { + /* Make sure we don't infinite loop on an ESC in the first half */ + static const char s[] = { 'A', 'B', 0x1B, ' ', 'D', '\0' }; + _cleanup_free_ char *t = NULL; + + t = ellipsize_mem(s, 5, 5, 50); + assert_se(t); + assert_se(memcmp(t, s, 5) == 0); +} + DEFINE_TEST_MAIN(LOG_INFO);