Skip to content

Commit efc44e6

Browse files
authored
Merge pull request #117 from IoTSharp/master
fix:fixed crash issues when the illegal topic is received
2 parents e723940 + d4b65dc commit efc44e6

File tree

3 files changed

+64
-28
lines changed

3 files changed

+64
-28
lines changed

common/mqtt_list.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
* @LastEditTime: 2020-04-27 23:28:12
66
* @Description: the following code references TencentOS tiny, please keep the author information and source code according to the license.
77
*/
8+
#include <stddef.h>
9+
#include "mqtt_list.h"
810

9-
# include "mqtt_list.h"
1011

1112
static void _mqtt_list_add(mqtt_list_t *node, mqtt_list_t *prev, mqtt_list_t *next)
1213
{
@@ -43,9 +44,13 @@ void mqtt_list_add_tail(mqtt_list_t *node, mqtt_list_t *list)
4344
_mqtt_list_add(node, list->prev, list);
4445
}
4546

46-
void mqtt_list_del(mqtt_list_t *entry)
47+
void mqtt_list_del(mqtt_list_t* entry)
4748
{
48-
_mqtt_list_del(entry->prev, entry->next);
49+
if (entry == NULL) return;
50+
if (entry->prev == NULL || entry->next == NULL) return;
51+
_mqtt_list_del(entry->prev, entry->next);
52+
entry->prev = NULL;
53+
entry->next = NULL;
4954
}
5055

5156
void mqtt_list_del_init(mqtt_list_t *entry)

mqtt/MQTTDeserializePublish.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ int MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retaine
5050
*qos = header.bits.qos;
5151
*retained = header.bits.retain;
5252

53-
curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
53+
curdata += MQTTPacket_decodeBuf(curdata, &mylen); /* read remaining length */
5454
enddata = curdata + mylen;
5555

5656
if (!readMQTTLenString(topicName, &curdata, enddata) ||

mqttclient/mqttclient.c

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -228,33 +228,58 @@ 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+
// topic_filter: The filter string used in subscription (may contain +/#), e.g. a/+/c or foo/#
232+
// topic_name: The actual topic received (should not contain wildcards), e.g. a/b/c or foo/bar
233+
static char mqtt_topic_is_matched(const char* topic_filter, MQTTString* topic_name)
232234
{
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;
235+
const char* filter = topic_filter;
236+
const char* topic = topic_name->lenstring.data;
237+
int topic_len = topic_name == NULL || topic_name->lenstring.data == NULL || topic_name->lenstring.len <= 0 ? 0 : strnlen(topic, topic_name->lenstring.len);
238+
int filter_len = strlen(filter);
239+
int i = 0, j = 0;
240+
while (i < filter_len && j < topic_len) {
241+
if (filter[i] == '#') {
242+
// '#' must be at the end and must be preceded by '/' or be the first character
243+
if ((i == filter_len - 1) && (i == 0 || filter[i - 1] == '/')) {
244+
return 1;
245+
}
246+
else {
247+
return 0;
248+
}
249+
}
250+
if (filter[i] == '+') {
251+
// '+' must occupy an entire level
252+
if ((i > 0 && filter[i - 1] != '/') || (i < filter_len - 1 && filter[i + 1] != '/' && filter[i + 1] != '\0')) {
253+
return 0;
254+
}
255+
// Skip one level in the topic
256+
while (j < topic_len && topic[j] != '/') j++;
257+
i++;
250258
}
251-
else if (*curf == '#')
252-
curn = curn_end - 1;
253-
curf++;
254-
curn++;
255-
};
259+
else {
260+
// Ordinary characters match one by one
261+
if (filter[i] != topic[j]) {
262+
return 0;
263+
}
264+
i++;
265+
j++;
266+
}
267+
// Skip '/'
268+
if (i < filter_len && filter[i] == '/' && j < topic_len && topic[j] == '/') {
269+
i++;
270+
j++;
271+
}
272+
}
256273

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

260285
static void mqtt_new_message_data(message_data_t* md, MQTTString* topic_name, mqtt_message_t* message)
@@ -442,8 +467,14 @@ static message_handlers_t *mqtt_msg_handler_create(const char* topic_filter, mqt
442467
static void mqtt_msg_handler_destory(message_handlers_t *msg_handler)
443468
{
444469
if (NULL != &msg_handler->list) {
470+
471+
if (msg_handler->list.prev == NULL || msg_handler->list.next == NULL) return;
472+
445473
mqtt_list_del(&msg_handler->list);
474+
msg_handler->list.prev == NULL;
475+
msg_handler->list.next == NULL;
446476
platform_memory_free(msg_handler);
477+
msg_handler = NULL;
447478
}
448479
}
449480

0 commit comments

Comments
 (0)