diff --git a/mongoose.c b/mongoose.c index e32264803d..12569e41b7 100644 --- a/mongoose.c +++ b/mongoose.c @@ -3159,6 +3159,7 @@ static int skip_chunk(const char *buf, int len, int *pl, int *dl) { int i = 0, n = 0; if (len < 3) return 0; while (i < len && is_hex_digit(buf[i])) i++; + if (i == 0) return -1; // Error, no length specified if (i > (int) sizeof(int) * 2) return -1; // Chunk length is too big if (len < i + 1 || buf[i] != '\r' || buf[i + 1] != '\n') return -1; // Error n = (int) mg_unhexn(buf, (size_t) i); // Decode chunk length diff --git a/src/http.c b/src/http.c index 16608089a0..b7c85ff0b1 100644 --- a/src/http.c +++ b/src/http.c @@ -1,7 +1,7 @@ -#include "http.h" #include "arch.h" #include "base64.h" #include "fmt.h" +#include "http.h" #include "json.h" #include "log.h" #include "net.h" @@ -962,6 +962,7 @@ static int skip_chunk(const char *buf, int len, int *pl, int *dl) { int i = 0, n = 0; if (len < 3) return 0; while (i < len && is_hex_digit(buf[i])) i++; + if (i == 0) return -1; // Error, no length specified if (i > (int) sizeof(int) * 2) return -1; // Chunk length is too big if (len < i + 1 || buf[i] != '\r' || buf[i + 1] != '\n') return -1; // Error n = (int) mg_unhexn(buf, (size_t) i); // Decode chunk length diff --git a/test/unit_test.c b/test/unit_test.c index a219b2a30c..dbc736ca01 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -1161,6 +1161,22 @@ static void test_http_server(void) { } #endif + // #2552, reject chunks with no length + ASSERT(fetch(&mgr, buf, url, + "POST / HTTP/1.1\r\n" + "Transfer-Encoding: chunked\r\n\r\n" + "1\r\n" + "Z\r\n" + "?\r\n" + "\r\n") == 0); + ASSERT(fetch(&mgr, buf, url, + "POST / HTTP/1.1\r\n" + "Transfer-Encoding: chunked\r\n\r\n" + "1\r\n" + "Z\r\n" + "\r\n" + "\r\n") == 0); + mg_mgr_free(&mgr); ASSERT(mgr.conns == NULL); } @@ -1605,11 +1621,11 @@ static void test_http_parse(void) { ASSERT(mg_http_parse(s, strlen(s), &hm) == (int) strlen(s)); s = "a\nb:b\nc:c\n\n"; ASSERT(mg_http_parse(s, strlen(s), &hm) < 0); - s = "a b\nc: \xc0\n\n"; // Invalid UTF in the header value: accept + s = "a b\nc: \xc0\n\n"; // Invalid UTF in the header value: accept ASSERT(mg_http_parse(s, strlen(s), &hm) == (int) strlen(s)); ASSERT((v = mg_http_get_header(&hm, "c")) != NULL); ASSERT(mg_vcmp(v, "\xc0") == 0); - s = "a b\n\xc0: 2\n\n"; // Invalid UTF in the header name: do NOT accept + s = "a b\n\xc0: 2\n\n"; // Invalid UTF in the header name: do NOT accept ASSERT(mg_http_parse(s, strlen(s), &hm) == -1); } }