Commit b3e0f780 authored by Sergey Lyubka's avatar Sergey Lyubka Committed by Cesanta Bot

Fix heap-based overflow in parse_mqtt

PUBLISHED_FROM=3306592896298597fff5269634df0c1a1555113b
parent 2bdbfc27
...@@ -10841,7 +10841,7 @@ static const char *scanto(const char *p, struct mg_str *s) { ...@@ -10841,7 +10841,7 @@ static const char *scanto(const char *p, struct mg_str *s) {
MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) {
uint8_t header; uint8_t header;
size_t len = 0, len_len = 0; size_t len = 0, len_len = 0;
const char *p, *end; const char *p, *end, *eop = &io->buf[io->len];
unsigned char lc = 0; unsigned char lc = 0;
int cmd; int cmd;
...@@ -10852,7 +10852,7 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { ...@@ -10852,7 +10852,7 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) {
/* decode mqtt variable length */ /* decode mqtt variable length */
len = len_len = 0; len = len_len = 0;
p = io->buf + 1; p = io->buf + 1;
while ((size_t)(p - io->buf) < io->len) { while (p < eop) {
lc = *((const unsigned char *) p++); lc = *((const unsigned char *) p++);
len += (lc & 0x7f) << 7 * len_len; len += (lc & 0x7f) << 7 * len_len;
len_len++; len_len++;
...@@ -10861,9 +10861,7 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { ...@@ -10861,9 +10861,7 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) {
} }
end = p + len; end = p + len;
if (lc & 0x80 || len > (io->len - (p - io->buf))) { if (lc & 0x80 || end > eop) return MG_MQTT_ERROR_INCOMPLETE_MSG;
return MG_MQTT_ERROR_INCOMPLETE_MSG;
}
mm->cmd = cmd; mm->cmd = cmd;
mm->qos = MG_MQTT_GET_QOS(header); mm->qos = MG_MQTT_GET_QOS(header);
...@@ -10917,7 +10915,9 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { ...@@ -10917,7 +10915,9 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) {
case MG_MQTT_CMD_PUBREL: case MG_MQTT_CMD_PUBREL:
case MG_MQTT_CMD_PUBCOMP: case MG_MQTT_CMD_PUBCOMP:
case MG_MQTT_CMD_SUBACK: case MG_MQTT_CMD_SUBACK:
if (end - p < 2) return MG_MQTT_ERROR_MALFORMED_MSG;
mm->message_id = getu16(p); mm->message_id = getu16(p);
p += 2;
break; break;
case MG_MQTT_CMD_PUBLISH: { case MG_MQTT_CMD_PUBLISH: {
p = scanto(p, &mm->topic); p = scanto(p, &mm->topic);
......
...@@ -24,7 +24,7 @@ static const char *scanto(const char *p, struct mg_str *s) { ...@@ -24,7 +24,7 @@ static const char *scanto(const char *p, struct mg_str *s) {
MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) {
uint8_t header; uint8_t header;
size_t len = 0, len_len = 0; size_t len = 0, len_len = 0;
const char *p, *end; const char *p, *end, *eop = &io->buf[io->len];
unsigned char lc = 0; unsigned char lc = 0;
int cmd; int cmd;
...@@ -35,7 +35,7 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { ...@@ -35,7 +35,7 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) {
/* decode mqtt variable length */ /* decode mqtt variable length */
len = len_len = 0; len = len_len = 0;
p = io->buf + 1; p = io->buf + 1;
while ((size_t)(p - io->buf) < io->len) { while (p < eop) {
lc = *((const unsigned char *) p++); lc = *((const unsigned char *) p++);
len += (lc & 0x7f) << 7 * len_len; len += (lc & 0x7f) << 7 * len_len;
len_len++; len_len++;
...@@ -44,9 +44,7 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { ...@@ -44,9 +44,7 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) {
} }
end = p + len; end = p + len;
if (lc & 0x80 || len > (io->len - (p - io->buf))) { if (lc & 0x80 || end > eop) return MG_MQTT_ERROR_INCOMPLETE_MSG;
return MG_MQTT_ERROR_INCOMPLETE_MSG;
}
mm->cmd = cmd; mm->cmd = cmd;
mm->qos = MG_MQTT_GET_QOS(header); mm->qos = MG_MQTT_GET_QOS(header);
...@@ -100,7 +98,9 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { ...@@ -100,7 +98,9 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) {
case MG_MQTT_CMD_PUBREL: case MG_MQTT_CMD_PUBREL:
case MG_MQTT_CMD_PUBCOMP: case MG_MQTT_CMD_PUBCOMP:
case MG_MQTT_CMD_SUBACK: case MG_MQTT_CMD_SUBACK:
if (end - p < 2) return MG_MQTT_ERROR_MALFORMED_MSG;
mm->message_id = getu16(p); mm->message_id = getu16(p);
p += 2;
break; break;
case MG_MQTT_CMD_PUBLISH: { case MG_MQTT_CMD_PUBLISH: {
p = scanto(p, &mm->topic); p = scanto(p, &mm->topic);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment