Skip to content

Commit c835856

Browse files
committed
Rewritten mqtt_topic_is_matched and fixed Segmentation fault
1 parent 1d831f5 commit c835856

File tree

1 file changed

+47
-24
lines changed

1 file changed

+47
-24
lines changed

mqttclient/mqttclient.c

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -228,33 +228,56 @@ static int mqtt_is_topic_equals(const char *topic_filter, const char *topic)
228228
return 0;
229229
}
230230

231-
static char mqtt_topic_is_matched(char* topic_filter, MQTTString* topic_name)
231+
static char mqtt_topic_is_matched(const char* topic_filter, MQTTString* topic_name)
232232
{
233-
char* curf = topic_filter;
234-
char* curn = topic_name->lenstring.data;
235-
char* curn_end = curn + topic_name->lenstring.len;
236-
237-
while (*curf && curn < curn_end)
238-
{
239-
if (*curn == '/' && *curf != '/')
240-
break;
241-
242-
/* support wildcards for MQTT topics, such as '#' '+' */
243-
if (*curf != '+' && *curf != '#' && *curf != *curn)
244-
break;
245-
246-
if (*curf == '+') {
247-
char* nextpos = curn + 1;
248-
while (nextpos < curn_end && *nextpos != '/')
249-
nextpos = ++curn + 1;
233+
const char* filter = topic_filter;
234+
const char* topic = topic_name->lenstring.data;
235+
int topic_len = topic_name != NULL && topic != NULL ? strnlen(topic, topic_name->lenstring.len) : 0;
236+
int filter_len = strlen(filter);
237+
int i = 0, j = 0;
238+
while (i < filter_len && j < topic_len) {
239+
if (filter[i] == '#') {
240+
// '#' must be at the end and must be preceded by '/' or be the first character
241+
if ((i == filter_len - 1) && (i == 0 || filter[i - 1] == '/')) {
242+
return 1;
243+
}
244+
else {
245+
return 0;
246+
}
247+
}
248+
if (filter[i] == '+') {
249+
// '+' must occupy an entire level
250+
if ((i > 0 && filter[i - 1] != '/') || (i < filter_len - 1 && filter[i + 1] != '/' && filter[i + 1] != '\0')) {
251+
return 0;
252+
}
253+
// Skip one level in the topic
254+
while (j < topic_len && topic[j] != '/') j++;
255+
i++;
250256
}
251-
else if (*curf == '#')
252-
curn = curn_end - 1;
253-
curf++;
254-
curn++;
255-
};
257+
else {
258+
// Ordinary characters match one by one
259+
if (filter[i] != topic[j]) {
260+
return 0;
261+
}
262+
i++;
263+
j++;
264+
}
265+
// Skip '/'
266+
if (i < filter_len && filter[i] == '/' && j < topic_len && topic[j] == '/') {
267+
i++;
268+
j++;
269+
}
270+
}
256271

257-
return (curn == curn_end) && (*curf == '\0');
272+
// Process ending
273+
if (i == filter_len && j == topic_len) {
274+
return 1;
275+
}
276+
// Allow ending with "/#" and topic is entirely consumed
277+
if ((i == filter_len - 2) && filter[i] == '/' && filter[i + 1] == '#' && j == topic_len) {
278+
return 1;
279+
}
280+
return 0;
258281
}
259282

260283
static void mqtt_new_message_data(message_data_t* md, MQTTString* topic_name, mqtt_message_t* message)

0 commit comments

Comments
 (0)