From af2ffcaba879407c024a5cdfd9981e4e25508421 Mon Sep 17 00:00:00 2001 From: Florian Cramer Date: Fri, 16 Dec 2022 19:20:53 +0100 Subject: [PATCH] AK: Make StringUtils::matches() handle escaping correctly Previously any backslash and the character following it were ignored. This commit adds a fall through to match the character following the backslash without checking whether it is "special". --- AK/StringUtils.cpp | 7 +++++-- Tests/AK/TestStringUtils.cpp | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/AK/StringUtils.cpp b/AK/StringUtils.cpp index d660b95f0f..bfa840bf81 100644 --- a/AK/StringUtils.cpp +++ b/AK/StringUtils.cpp @@ -62,8 +62,11 @@ bool matches(StringView str, StringView mask, CaseSensitivity case_sensitivity, record_span(string_ptr - string_start, 1); break; case '\\': - ++mask_ptr; - break; + // if backslash is last character in mask, just treat it as an exact match + // otherwise use it as escape for next character + if (mask_ptr + 1 < mask_end) + ++mask_ptr; + [[fallthrough]]; default: auto p = *mask_ptr; auto ch = *string_ptr; diff --git a/Tests/AK/TestStringUtils.cpp b/Tests/AK/TestStringUtils.cpp index d0155c049e..93b4c45157 100644 --- a/Tests/AK/TestStringUtils.cpp +++ b/Tests/AK/TestStringUtils.cpp @@ -76,6 +76,21 @@ TEST_CASE(matches_trailing) EXPECT(AK::StringUtils::matches("ab"sv, "*ab****"sv)); } +TEST_CASE(match_backslash_escape) +{ + EXPECT(AK::StringUtils::matches("ab*"sv, "ab\\*"sv)); + EXPECT(!AK::StringUtils::matches("abc"sv, "ab\\*"sv)); + EXPECT(!AK::StringUtils::matches("abcd"sv, "ab\\*"sv)); + EXPECT(AK::StringUtils::matches("ab?"sv, "ab\\?"sv)); + EXPECT(!AK::StringUtils::matches("abc"sv, "ab\\?"sv)); +} + +TEST_CASE(match_trailing_backslash) +{ + EXPECT(AK::StringUtils::matches("x\\"sv, "x\\"sv)); + EXPECT(AK::StringUtils::matches("x\\"sv, "x\\\\"sv)); +} + TEST_CASE(convert_to_int) { auto value = AK::StringUtils::convert_to_int(StringView());