From 98fb8fb38fa208af74ccf75e5077d81005e5f5dd Mon Sep 17 00:00:00 2001 From: mkaruza Date: Mon, 28 Apr 2025 11:54:54 +0200 Subject: [PATCH] fix(glob): Correctly match longer strings with '*' or '**' pattern (#5001) * fix(glob): Correctly match longer strings with '*' or '**' pattern If string is longer than 16 chars we are using reflex library for matching. When used pattern is '*' or '**' we are going to remove trailing and leading star and have empty pattern. We should, in this, edge case set manually star pattern. Fixes #4948 Signed-off-by: mkaruza * Core matching test --------- Signed-off-by: mkaruza --- src/core/dfly_core_test.cc | 1 + src/core/glob_matcher.cc | 6 +++++- src/server/dragonfly_test.cc | 17 +++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/core/dfly_core_test.cc b/src/core/dfly_core_test.cc index 3eb6bdafe..e8ca8a669 100644 --- a/src/core/dfly_core_test.cc +++ b/src/core/dfly_core_test.cc @@ -155,6 +155,7 @@ TEST_F(StringMatchTest, Basic) { // Wildcards EXPECT_EQ(MatchLen("*", "hello", 0), 1); + EXPECT_EQ(MatchLen("*", "1234567890123456", 0), 1); EXPECT_EQ(MatchLen("h*", "hello", 0), 1); EXPECT_EQ(MatchLen("h*", "abc", 0), 0); EXPECT_EQ(MatchLen("h*o", "hello", 0), 1); diff --git a/src/core/glob_matcher.cc b/src/core/glob_matcher.cc index 24bee465e..72ae36a31 100644 --- a/src/core/glob_matcher.cc +++ b/src/core/glob_matcher.cc @@ -236,7 +236,11 @@ GlobMatcher::GlobMatcher(string_view pattern, bool case_sensitive) regex.push_back('i'); } regex.push_back(')'); - regex.append(Glob2Regex(pattern)); + if (pattern.empty()) { + regex.append(Glob2Regex("*")); + } else { + regex.append(Glob2Regex(pattern)); + } matcher_.pattern(regex); #elif USE_PCRE2 string regex("(?s"); // dotall mode diff --git a/src/server/dragonfly_test.cc b/src/server/dragonfly_test.cc index 8e7e80584..829f05e5a 100644 --- a/src/server/dragonfly_test.cc +++ b/src/server/dragonfly_test.cc @@ -548,6 +548,23 @@ TEST_F(DflyEngineTest, PSubscribe) { EXPECT_EQ("a*", msg.pattern); } +TEST_F(DflyEngineTest, PSubscribeMatchOnlyStar) { + single_response_ = false; + auto resp = pp_->at(1)->Await([&] { return Run({"psubscribe", "*"}); }); + EXPECT_THAT(resp, ArrLen(3)); + resp = pp_->at(0)->Await([&] { return Run({"PUBLISH", "1234567890123456", "abc"}); }); + EXPECT_THAT(resp, IntArg(1)); + + pp_->AwaitFiberOnAll([](ProactorBase* pb) {}); + + ASSERT_EQ(1, SubscriberMessagesLen("IO1")); + + const auto& msg = GetPublishedMessage("IO1", 0); + EXPECT_EQ("abc", msg.message); + EXPECT_EQ("1234567890123456", msg.channel); + EXPECT_EQ("*", msg.pattern); +} + TEST_F(DflyEngineTest, Unsubscribe) { auto resp = Run({"unsubscribe", "a"}); EXPECT_THAT(resp.GetVec(), ElementsAre("unsubscribe", "a", IntArg(0)));