Fix mosquitto_topic_matches_sub2() not using the length parameters.
Closes #2364. Thanks to Jens Alfke.
This commit is contained in:
parent
0d0a36906c
commit
11975332d4
@ -4,6 +4,11 @@
|
|||||||
Broker:
|
Broker:
|
||||||
- Fix bridge not respecting receive-maximum when reconnecting with MQTT v5.
|
- 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
|
2.0.13 - 2021-10-27
|
||||||
===================
|
===================
|
||||||
|
|
||||||
|
137
lib/util_topic.c
137
lib/util_topic.c
@ -189,19 +189,11 @@ int mosquitto_sub_topic_check2(const char *str, size_t len)
|
|||||||
return MOSQ_ERR_SUCCESS;
|
return MOSQ_ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Does a topic match a subscription? */
|
||||||
int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result)
|
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)
|
|
||||||
{
|
{
|
||||||
size_t spos;
|
size_t spos;
|
||||||
|
|
||||||
UNUSED(sublen);
|
|
||||||
UNUSED(topiclen);
|
|
||||||
|
|
||||||
if(!result) return MOSQ_ERR_INVAL;
|
if(!result) return MOSQ_ERR_INVAL;
|
||||||
*result = false;
|
*result = false;
|
||||||
|
|
||||||
@ -325,3 +317,130 @@ int mosquitto_topic_matches_sub2(const char *sub, size_t sublen, const char *top
|
|||||||
|
|
||||||
return MOSQ_ERR_SUCCESS;
|
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;
|
||||||
|
}
|
||||||
|
@ -11,6 +11,16 @@ static void match_helper(const char *sub, const char *topic)
|
|||||||
rc = mosquitto_topic_matches_sub(sub, topic, &match);
|
rc = mosquitto_topic_matches_sub(sub, topic, &match);
|
||||||
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
|
CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
|
||||||
CU_ASSERT_EQUAL(match, true);
|
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)
|
static void no_match_helper(int rc_expected, const char *sub, const char *topic)
|
||||||
@ -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);
|
printf("%d:%d %s:%s\n", rc, rc_expected, sub, topic);
|
||||||
}
|
}
|
||||||
CU_ASSERT_EQUAL(match, false);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================================================================
|
/* ========================================================================
|
||||||
|
Loading…
Reference in New Issue
Block a user