diff --git a/lib/mqtt.c b/lib/mqtt.c
index d88fa737d..d49a5f1cc 100644
--- a/lib/mqtt.c
+++ b/lib/mqtt.c
@@ -477,6 +477,12 @@ static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)
/* -- switched state -- */
remlen = mq->remaining_length;
infof(data, "Remaining length: %zd bytes\n", remlen);
+ if(data->set.max_filesize &&
+ (curl_off_t)remlen > data->set.max_filesize) {
+ failf(data, "Maximum file size exceeded");
+ result = CURLE_FILESIZE_EXCEEDED;
+ goto end;
+ }
Curl_pgrsSetDownloadSize(data, remlen);
data->req.bytecount = 0;
data->req.size = remlen;
@@ -582,6 +588,10 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
Curl_debug(data, CURLINFO_HEADER_IN, (char *)&byte, 1);
pkt[mq->npacket++] = byte;
} while((byte & 0x80) && (mq->npacket < 4));
+ if(nread && (byte & 0x80))
+ /* MQTT supports up to 127 * 128^0 + 127 * 128^1 + 127 * 128^2 +
+ 127 * 128^3 bytes. server tried to send more */
+ result = CURLE_WEIRD_SERVER_REPLY;
if(result)
break;
mq->remaining_length = mqtt_decode_len(&pkt[0], mq->npacket, NULL);
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 77feeccee..2b25a92b3 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -232,4 +232,6 @@ test2100 \
\
test3000 test3001 test3002 test3003 test3004 test3005 test3006 test3007 \
test3008 test3009 test3010 test3011 test3012 test3013 test3014 test3015 \
-test3016
+test3016 \
+\
+test3017 test3018
diff --git a/tests/data/test3017 b/tests/data/test3017
new file mode 100644
index 000000000..4d907b39f
--- /dev/null
+++ b/tests/data/test3017
@@ -0,0 +1,67 @@
+
+
+
+MQTT
+MQTT SUBSCRIBE
+
+
+
+#
+# Server-side
+
+
+hello
+
+
+00 04 33 30 31 37 68 65 6c 6c 6f 5b 4c 46 5d 0a
+
+
+excessive-remaining TRUE
+
+
+
+#
+# Client-side
+
+
+mqtt
+
+
+mqtt
+
+
+MQTT SUBSCRIBE with pathological PUBLISH length
+
+
+mqtt://%HOSTIP:%MQTTPORT/%TESTNUMBER -m 3
+
+
+
+#
+# Verify data after the test has been "shot"
+
+# These are hexadecimal protocol dumps from the client
+#
+# Strip out the random part of the client id from the CONNECT message
+# before comparison
+
+s/^(.* 00044d5154540402003c000c6375726c).*/$1/
+
+# on windows the disconnect is never seen - no idea why
+
+^server DISCONNECT 0 e000
+
+
+client CONNECT 18 00044d5154540402003c000c6375726c
+server CONNACK 2 20020000
+client SUBSCRIBE 9 000100043330313700
+server SUBACK 3 9003000100
+server PUBLISH c 30ffffff8000043330313768656c6c6f0a
+
+
+# 8 is CURLE_WEIRD_SERVER_REPLY
+
+8
+
+
+
diff --git a/tests/data/test3018 b/tests/data/test3018
new file mode 100644
index 000000000..71e06b593
--- /dev/null
+++ b/tests/data/test3018
@@ -0,0 +1,65 @@
+
+
+
+MQTT
+MQTT SUBSCRIBE
+--max-filesize
+
+
+
+#
+# Server-side
+
+
+hello
+
+
+00 04 33 30 31 38 68 65 6c 6c 6f 5b 4c 46 5d 0a
+
+
+
+#
+# Client-side
+
+
+mqtt
+
+
+mqtt
+
+
+MQTT SUBSCRIBE with PUBLISH larger than --max-filesize
+
+
+mqtt://%HOSTIP:%MQTTPORT/%TESTNUMBER --max-filesize 11
+
+
+
+#
+# Verify data after the test has been "shot"
+
+# These are hexadecimal protocol dumps from the client
+#
+# Strip out the random part of the client id from the CONNECT message
+# before comparison
+
+s/^(.* 00044d5154540402003c000c6375726c).*/$1/
+
+# on windows the disconnect is never seen - no idea why
+
+^server DISCONNECT 0 e000
+
+
+client CONNECT 18 00044d5154540402003c000c6375726c
+server CONNACK 2 20020000
+client SUBSCRIBE 9 000100043330313800
+server SUBACK 3 9003000100
+server PUBLISH c 300c00043330313868656c6c6f0a
+
+
+# 63 is CURLE_FILESIZE_EXCEEDED
+
+63
+
+
+
diff --git a/tests/server/mqttd.c b/tests/server/mqttd.c
index 8134336da..18339262e 100644
--- a/tests/server/mqttd.c
+++ b/tests/server/mqttd.c
@@ -106,6 +106,7 @@ struct configurable {
this */
bool publish_before_suback;
bool short_publish;
+ bool excessive_remaining;
unsigned char error_connack;
int testnum;
};
@@ -130,6 +131,7 @@ static void resetdefaults(void)
config.version = CONFIG_VERSION;
config.publish_before_suback = FALSE;
config.short_publish = FALSE;
+ config.excessive_remaining = FALSE;
config.error_connack = 0;
config.testnum = 0;
}
@@ -171,6 +173,10 @@ static void getconfig(void)
config.testnum = atoi(value);
logmsg("testnum = %d", config.testnum);
}
+ else if(!strcmp(key, "excessive-remaining")) {
+ logmsg("excessive-remaining set");
+ config.excessive_remaining = TRUE;
+ }
}
}
fclose(fp);
@@ -337,7 +343,8 @@ static int disconnect(FILE *dump, curl_socket_t fd)
*/
/* return number of bytes used */
-static int encode_length(size_t packetlen, char *remlength) /* 4 bytes */
+static int encode_length(size_t packetlen,
+ unsigned char *remlength) /* 4 bytes */
{
int bytes = 0;
unsigned char encode;
@@ -393,10 +400,19 @@ static int publish(FILE *dump,
ssize_t packetlen;
ssize_t sendamount;
ssize_t rc;
- char rembuffer[4];
+ unsigned char rembuffer[4];
int encodedlen;
- encodedlen = encode_length(remaininglength, rembuffer);
+ if(config.excessive_remaining) {
+ /* manually set illegal remaining length */
+ rembuffer[0] = 0xff;
+ rembuffer[1] = 0xff;
+ rembuffer[2] = 0xff;
+ rembuffer[3] = 0x80; /* maximum allowed here by spec is 0x7f */
+ encodedlen = 4;
+ }
+ else
+ encodedlen = encode_length(remaininglength, rembuffer);
/* one packet type byte (possibly two more for packetid) */
packetlen = remaininglength + encodedlen + 1;