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.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user