Skip to content

Commit

Permalink
Fix mosquitto_topic_matches_sub2() not using the length parameters.
Browse files Browse the repository at this point in the history
Closes #2364. Thanks to Jens Alfke.
  • Loading branch information
ralight committed Nov 16, 2021
1 parent 0d0a369 commit 1197533
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 9 deletions.
5 changes: 5 additions & 0 deletions ChangeLog.txt
Expand Up @@ -4,6 +4,11 @@
Broker:
- Fix bridge not respecting receive-maximum when reconnecting with MQTT v5.

Client library:
- Fix mosquitto_topic_matches_sub2() not using the length parameters.
Closes #2364.


2.0.13 - 2021-10-27
===================

Expand Down
137 changes: 128 additions & 9 deletions lib/util_topic.c
Expand Up @@ -189,19 +189,11 @@ int mosquitto_sub_topic_check2(const char *str, size_t len)
return MOSQ_ERR_SUCCESS;
}

int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result)
{
return mosquitto_topic_matches_sub2(sub, 0, topic, 0, result);
}

/* Does a topic match a subscription? */
int mosquitto_topic_matches_sub2(const char *sub, size_t sublen, const char *topic, size_t topiclen, bool *result)
int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result)
{
size_t spos;

UNUSED(sublen);
UNUSED(topiclen);

if(!result) return MOSQ_ERR_INVAL;
*result = false;

Expand Down Expand Up @@ -325,3 +317,130 @@ int mosquitto_topic_matches_sub2(const char *sub, size_t sublen, const char *top

return MOSQ_ERR_SUCCESS;
}

/* Does a topic match a subscription? */
int mosquitto_topic_matches_sub2(const char *sub, size_t sublen, const char *topic, size_t topiclen, bool *result)
{
size_t spos, tpos;

if(!result) return MOSQ_ERR_INVAL;
*result = false;

if(!sub || !topic || !sublen || !topiclen){
return MOSQ_ERR_INVAL;
}

if((sub[0] == '$' && topic[0] != '$')
|| (topic[0] == '$' && sub[0] != '$')){

return MOSQ_ERR_SUCCESS;
}

spos = 0;
tpos = 0;

while(spos < sublen){
if(tpos < topiclen && (topic[tpos] == '+' || topic[tpos] == '#')){
return MOSQ_ERR_INVAL;
}
if(tpos == topiclen || sub[spos] != topic[tpos]){
if(sub[spos] == '+'){
/* Check for bad "+foo" or "a/+foo" subscription */
if(spos > 0 && sub[spos-1] != '/'){
return MOSQ_ERR_INVAL;
}
/* Check for bad "foo+" or "foo+/a" subscription */
if(spos+1 < sublen && sub[spos+1] != '/'){
return MOSQ_ERR_INVAL;
}
spos++;
while(tpos < topiclen && topic[tpos] != '/'){
if(topic[tpos] == '+' || topic[tpos] == '#'){
return MOSQ_ERR_INVAL;
}
tpos++;
}
if(tpos == topiclen && spos == sublen){
*result = true;
return MOSQ_ERR_SUCCESS;
}
}else if(sub[spos] == '#'){
/* Check for bad "foo#" subscription */
if(spos > 0 && sub[spos-1] != '/'){
return MOSQ_ERR_INVAL;
}
/* Check for # not the final character of the sub, e.g. "#foo" */
if(spos+1 < sublen){
return MOSQ_ERR_INVAL;
}else{
while(tpos < topiclen){
if(topic[tpos] == '+' || topic[tpos] == '#'){
return MOSQ_ERR_INVAL;
}
tpos++;
}
*result = true;
return MOSQ_ERR_SUCCESS;
}
}else{
/* Check for e.g. foo/bar matching foo/+/# */
if(tpos == topiclen
&& spos > 0
&& sub[spos-1] == '+'
&& sub[spos] == '/'
&& spos+1 < sublen
&& sub[spos+1] == '#')
{
*result = true;
return MOSQ_ERR_SUCCESS;
}

/* There is no match at this point, but is the sub invalid? */
while(spos < sublen){
if(sub[spos] == '#' && spos+1 < sublen){
return MOSQ_ERR_INVAL;
}
spos++;
}

/* Valid input, but no match */
return MOSQ_ERR_SUCCESS;
}
}else{
/* sub[spos] == topic[tpos] */
if(tpos+1 == topiclen){
/* Check for e.g. foo matching foo/# */
if(spos+3 == sublen
&& sub[spos+1] == '/'
&& sub[spos+2] == '#'){
*result = true;
return MOSQ_ERR_SUCCESS;
}
}
spos++;
tpos++;
if(spos == sublen && tpos == topiclen){
*result = true;
return MOSQ_ERR_SUCCESS;
}else if(tpos == topiclen && sub[spos] == '+' && spos+1 == sublen){
if(spos > 0 && sub[spos-1] != '/'){
return MOSQ_ERR_INVAL;
}
spos++;
*result = true;
return MOSQ_ERR_SUCCESS;
}
}
}
if(tpos < topiclen || spos < sublen){
*result = false;
}
while(tpos < topiclen){
if(topic[tpos] == '+' || topic[tpos] == '#'){
return MOSQ_ERR_INVAL;
}
tpos++;
}

return MOSQ_ERR_SUCCESS;
}
17 changes: 17 additions & 0 deletions test/unit/util_topic_test.c
Expand Up @@ -11,6 +11,16 @@ static void match_helper(const char *sub, const char *topic)
rc = mosquitto_topic_matches_sub(sub, topic, &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
if(match == false){
printf("1: %s:%s\n", sub, topic);
}

rc = mosquitto_topic_matches_sub2(sub, strlen(sub), topic, strlen(topic), &match);
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
CU_ASSERT_EQUAL(match, true);
if(match == false){
printf("2: %s:%s\n", sub, topic);
}
}

static void no_match_helper(int rc_expected, const char *sub, const char *topic)
Expand All @@ -24,6 +34,13 @@ static void no_match_helper(int rc_expected, const char *sub, const char *topic)
printf("%d:%d %s:%s\n", rc, rc_expected, sub, topic);
}
CU_ASSERT_EQUAL(match, false);

rc = mosquitto_topic_matches_sub2(sub, strlen(sub), topic, strlen(topic), &match);
CU_ASSERT_EQUAL(rc, rc_expected);
if(rc != rc_expected){
printf("%d:%d %s:%s\n", rc, rc_expected, sub, topic);
}
CU_ASSERT_EQUAL(match, false);
}

/* ========================================================================
Expand Down

0 comments on commit 1197533

Please sign in to comment.