Fix mg_url_decode fuzz

This commit is contained in:
cpq 2020-12-11 09:35:50 +00:00
parent 369f44adfa
commit 1b551741b8
5 changed files with 26 additions and 10 deletions

View File

@ -433,9 +433,10 @@ int mg_http_get_var(const struct mg_str *buf, const char *name, char *dst,
int mg_url_decode(const char *src, size_t src_len, char *dst, size_t dst_len, int mg_url_decode(const char *src, size_t src_len, char *dst, size_t dst_len,
int is_form_url_encoded) { int is_form_url_encoded) {
size_t i, j; size_t i, j;
for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) { for (i = j = 0; i < src_len && j + 1 < dst_len; i++, j++) {
if (src[i] == '%') { if (src[i] == '%') {
if (i < src_len - 2 && isxdigit(*(const unsigned char *) (src + i + 1)) && // Use `i + 2 < src_len`, not `i < src_len - 2`, note small src_len
if (i + 2 < src_len && isxdigit(*(const unsigned char *) (src + i + 1)) &&
isxdigit(*(const unsigned char *) (src + i + 2))) { isxdigit(*(const unsigned char *) (src + i + 2))) {
mg_unhex(src + i + 1, 2, (uint8_t *) &dst[j]); mg_unhex(src + i + 1, 2, (uint8_t *) &dst[j]);
i += 2; i += 2;
@ -448,7 +449,7 @@ int mg_url_decode(const char *src, size_t src_len, char *dst, size_t dst_len,
dst[j] = src[i]; dst[j] = src[i];
} }
} }
dst[j] = '\0'; // Null-terminate the destination if (j < dst_len) dst[j] = '\0'; // Null-terminate the destination
return i >= src_len ? (int) j : -1; return i >= src_len ? (int) j : -1;
} }
@ -1735,7 +1736,7 @@ static int parse(const uint8_t *in, size_t inlen, struct mqtt_message *m) {
len += (lc & 0x7f) << 7 * len_len; len += (lc & 0x7f) << 7 * len_len;
len_len++; len_len++;
if (!(lc & 0x80)) break; if (!(lc & 0x80)) break;
if (len_len > 4) return MQTT_MALFORMED; if (len_len >= 4) return MQTT_MALFORMED;
} }
end = p + len; end = p + len;

View File

@ -73,9 +73,10 @@ int mg_http_get_var(const struct mg_str *buf, const char *name, char *dst,
int mg_url_decode(const char *src, size_t src_len, char *dst, size_t dst_len, int mg_url_decode(const char *src, size_t src_len, char *dst, size_t dst_len,
int is_form_url_encoded) { int is_form_url_encoded) {
size_t i, j; size_t i, j;
for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) { for (i = j = 0; i < src_len && j + 1 < dst_len; i++, j++) {
if (src[i] == '%') { if (src[i] == '%') {
if (i < src_len - 2 && isxdigit(*(const unsigned char *) (src + i + 1)) && // Use `i + 2 < src_len`, not `i < src_len - 2`, note small src_len
if (i + 2 < src_len && isxdigit(*(const unsigned char *) (src + i + 1)) &&
isxdigit(*(const unsigned char *) (src + i + 2))) { isxdigit(*(const unsigned char *) (src + i + 2))) {
mg_unhex(src + i + 1, 2, (uint8_t *) &dst[j]); mg_unhex(src + i + 1, 2, (uint8_t *) &dst[j]);
i += 2; i += 2;
@ -88,7 +89,7 @@ int mg_url_decode(const char *src, size_t src_len, char *dst, size_t dst_len,
dst[j] = src[i]; dst[j] = src[i];
} }
} }
dst[j] = '\0'; // Null-terminate the destination if (j < dst_len) dst[j] = '\0'; // Null-terminate the destination
return i >= src_len ? (int) j : -1; return i >= src_len ? (int) j : -1;
} }

View File

@ -150,7 +150,7 @@ static int parse(const uint8_t *in, size_t inlen, struct mqtt_message *m) {
len += (lc & 0x7f) << 7 * len_len; len += (lc & 0x7f) << 7 * len_len;
len_len++; len_len++;
if (!(lc & 0x80)) break; if (!(lc & 0x80)) break;
if (len_len > 4) return MQTT_MALFORMED; if (len_len >= 4) return MQTT_MALFORMED;
} }
end = p + len; end = p + len;

View File

@ -11,6 +11,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
struct mg_str body = mg_str_n((const char *) data, size); struct mg_str body = mg_str_n((const char *) data, size);
char tmp[256]; char tmp[256];
mg_http_get_var(&body, "key", tmp, sizeof(tmp)); mg_http_get_var(&body, "key", tmp, sizeof(tmp));
mg_url_decode((char *) data, size, tmp, sizeof(tmp), 1);
mg_url_decode((char *) data, size, tmp, 1, 1);
struct mg_mqtt_message mm; struct mg_mqtt_message mm;
mg_mqtt_parse(data, size, &mm); mg_mqtt_parse(data, size, &mm);

View File

@ -92,6 +92,8 @@ static void test_http_get_var(void) {
body = mg_str("key=broken%2x"); body = mg_str("key=broken%2x");
ASSERT(mg_http_get_var(&body, "key", buf, sizeof(buf)) == -3); ASSERT(mg_http_get_var(&body, "key", buf, sizeof(buf)) == -3);
ASSERT(mg_http_get_var(&body, "inexistent", buf, sizeof(buf)) == -4); ASSERT(mg_http_get_var(&body, "inexistent", buf, sizeof(buf)) == -4);
body = mg_str("key=%");
ASSERT(mg_http_get_var(&body, "key", buf, sizeof(buf)) == -3);
} }
static int vcmp(struct mg_str s1, const char *s2) { static int vcmp(struct mg_str s1, const char *s2) {
@ -270,6 +272,12 @@ static void test_mqtt(void) {
int i; int i;
mg_mgr_init(&mgr); mg_mgr_init(&mgr);
{
uint8_t bad[] = " \xff\xff\xff\xff ";
struct mg_mqtt_message mm;
mg_mqtt_parse(bad, sizeof(bad), &mm);
}
// Connect with empty client ID // Connect with empty client ID
c = mg_mqtt_connect(&mgr, url, NULL, mqtt_cb, buf); c = mg_mqtt_connect(&mgr, url, NULL, mqtt_cb, buf);
for (i = 0; i < 100 && buf[0] == 0; i++) mg_mgr_poll(&mgr, 10); for (i = 0; i < 100 && buf[0] == 0; i++) mg_mgr_poll(&mgr, 10);
@ -859,12 +867,17 @@ static void test_util(void) {
ASSERT(mg_file_write("data.txt", "%s", "hi") == 2); ASSERT(mg_file_write("data.txt", "%s", "hi") == 2);
ASSERT(strcmp(mg_ntoa(0x100007f, buf, sizeof(buf)), "127.0.0.1") == 0); ASSERT(strcmp(mg_ntoa(0x100007f, buf, sizeof(buf)), "127.0.0.1") == 0);
ASSERT(strcmp(mg_hex("abc", 3, buf), "616263") == 0); ASSERT(strcmp(mg_hex("abc", 3, buf), "616263") == 0);
{
char bad[] = {'a', '=', '%'};
ASSERT(mg_url_decode(bad, sizeof(bad), buf, sizeof(buf), 0) < 0);
}
} }
int main(void) { int main(void) {
mg_log_set("3"); mg_log_set("3");
test_str();
test_util(); test_util();
test_mqtt();
test_str();
test_timer(); test_timer();
test_http_range(); test_http_range();
test_url(); test_url();
@ -875,7 +888,6 @@ int main(void) {
test_http_get_var(); test_http_get_var();
test_tls(); test_tls();
test_ws(); test_ws();
test_mqtt();
test_http_parse(); test_http_parse();
test_http_server(); test_http_server();
test_http_client(); test_http_client();