From 9ff56eefd0ec98ab8aaf053ac0aeb5641ad7ea0a Mon Sep 17 00:00:00 2001 From: Roger Light Date: Thu, 8 May 2014 22:56:16 +0100 Subject: [PATCH] Fix topic matching edge case. Thanks to Tobias Assarsson. --- ChangeLog.txt | 3 +++ lib/util_mosq.c | 20 ++++++++++---------- test/lib/c/09-util-topic-matching.c | 3 +++ 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index a9c9dd9f..49491e01 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -4,6 +4,9 @@ Broker: - Ensure that bridges verify certificates by default when using TLS. +Client library: +- Fix topic matching edge case. + 1.3.1 - 20140324 ================ diff --git a/lib/util_mosq.c b/lib/util_mosq.c index de7b5004..ea71c86e 100644 --- a/lib/util_mosq.c +++ b/lib/util_mosq.c @@ -216,6 +216,16 @@ int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result while(spos < slen && tpos < tlen){ if(sub[spos] == topic[tpos]){ + if(tpos == tlen-1){ + /* Check for e.g. foo matching foo/# */ + if(spos == slen-3 + && sub[spos+1] == '/' + && sub[spos+2] == '#'){ + *result = true; + multilevel_wildcard = true; + return MOSQ_ERR_SUCCESS; + } + } spos++; tpos++; if(spos == slen && tpos == tlen){ @@ -250,16 +260,6 @@ int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result return MOSQ_ERR_SUCCESS; } } - if(tpos == tlen-1){ - /* Check for e.g. foo matching foo/# */ - if(spos == slen-3 - && sub[spos+1] == '/' - && sub[spos+2] == '#'){ - *result = true; - multilevel_wildcard = true; - return MOSQ_ERR_SUCCESS; - } - } } if(multilevel_wildcard == false && (tpos < tlen || spos < slen)){ *result = false; diff --git a/test/lib/c/09-util-topic-matching.c b/test/lib/c/09-util-topic-matching.c index 8ffaed2b..dac546b6 100644 --- a/test/lib/c/09-util-topic-matching.c +++ b/test/lib/c/09-util-topic-matching.c @@ -16,10 +16,13 @@ void do_check(const char *sub, const char *topic, bool bad_res) int main(int argc, char *argv[]) { + do_check("test/6/#", "test/3", true); do_check("foo/bar", "foo/bar", false); do_check("foo/+", "foo/bar", false); do_check("foo/+/baz", "foo/bar/baz", false); + do_check("A/B/+/#", "A/B/B/C", false); + do_check("foo/+/#", "foo/bar/baz", false); do_check("#", "foo/bar/baz", false);