diff --git a/mongoose.c b/mongoose.c index 669e17f9..636e0bac 100644 --- a/mongoose.c +++ b/mongoose.c @@ -2401,7 +2401,7 @@ int mg_url_decode(const char *src, size_t src_len, char *dst, size_t dst_len, } static bool isok(uint8_t c) { - return c == '\n' || c == '\r' || c >= ' '; + return c == '\n' || c == '\r' || c == '\t' || c >= ' '; } int mg_http_get_request_len(const unsigned char *buf, size_t buf_len) { @@ -2463,9 +2463,11 @@ static bool mg_http_parse_headers(const char *s, const char *end, if (s >= end || clen(s, end) == 0) return false; // Invalid UTF-8 if (*s++ != ':') return false; // Invalid, not followed by : // if (clen(s, end) == 0) return false; // Invalid UTF-8 - while (s < end && s[0] == ' ') s++; // Skip spaces + while (s < end && (s[0] == ' ' || s[0] == '\t')) s++; // Skip spaces if ((s = skiptorn(s, end, &v)) == NULL) return false; - while (v.len > 0 && v.buf[v.len - 1] == ' ') v.len--; // Trim spaces + while (v.len > 0 && (v.buf[v.len - 1] == ' ' || v.buf[v.len - 1] == '\t')) { + v.len--; // Trim spaces + } // MG_INFO(("--HH [%.*s] [%.*s]", (int) k.len, k.buf, (int) v.len, v.buf)); h[i].name = k, h[i].value = v; // Success. Assign values } diff --git a/src/http.c b/src/http.c index 6cff55e0..1f6b39d4 100644 --- a/src/http.c +++ b/src/http.c @@ -185,7 +185,7 @@ int mg_url_decode(const char *src, size_t src_len, char *dst, size_t dst_len, } static bool isok(uint8_t c) { - return c == '\n' || c == '\r' || c >= ' '; + return c == '\n' || c == '\r' || c == '\t' || c >= ' '; } int mg_http_get_request_len(const unsigned char *buf, size_t buf_len) { @@ -247,9 +247,11 @@ static bool mg_http_parse_headers(const char *s, const char *end, if (s >= end || clen(s, end) == 0) return false; // Invalid UTF-8 if (*s++ != ':') return false; // Invalid, not followed by : // if (clen(s, end) == 0) return false; // Invalid UTF-8 - while (s < end && s[0] == ' ') s++; // Skip spaces + while (s < end && (s[0] == ' ' || s[0] == '\t')) s++; // Skip spaces if ((s = skiptorn(s, end, &v)) == NULL) return false; - while (v.len > 0 && v.buf[v.len - 1] == ' ') v.len--; // Trim spaces + while (v.len > 0 && (v.buf[v.len - 1] == ' ' || v.buf[v.len - 1] == '\t')) { + v.len--; // Trim spaces + } // MG_INFO(("--HH [%.*s] [%.*s]", (int) k.len, k.buf, (int) v.len, v.buf)); h[i].name = k, h[i].value = v; // Success. Assign values } diff --git a/test/unit_test.c b/test/unit_test.c index e23d5ae9..68e862ca 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -868,6 +868,10 @@ static void test_http_server(void) { ASSERT(cmpbody(buf, "hello\n") == 0); ASSERT(cmpheader(buf, "C", "D")); + ASSERT(fetch(&mgr, buf, url, "GET /a.txt HTTP/1.0\nA:\tB\n\n") == 200); + ASSERT(cmpbody(buf, "hello\n") == 0); + ASSERT(cmpheader(buf, "C", "D")); + // Invalid header: failure ASSERT(fetch(&mgr, buf, url, "GET /a.txt HTTP/1.0\nA B\n\n") == 0); @@ -1613,6 +1617,22 @@ static void test_http_parse(void) { 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); } + + { + struct mg_http_message hm; + const char *s; + s = "a b c\nd:e\n\n"; + ASSERT(mg_http_parse(s, strlen(s), &hm) == (int) strlen(s)); + s = "a b c\nd: e\n\n"; + ASSERT(mg_http_parse(s, strlen(s), &hm) == (int) strlen(s)); + s = "a b c\nd:\te\n\n"; + ASSERT(mg_http_parse(s, strlen(s), &hm) == (int) strlen(s)); + s = "a b c\nd:\t e\n\n"; + ASSERT(mg_http_parse(s, strlen(s), &hm) == (int) strlen(s)); + s = "a b c\nd: \te\t \n\n"; + ASSERT(mg_http_parse(s, strlen(s), &hm) == (int) strlen(s)); + ASSERT(mg_strcmp(hm.headers[0].value, mg_str("e")) == 0); + } } static void ehr(struct mg_connection *c, int ev, void *ev_data) {