Skip to content

Commit 5dff282

Browse files
committed
Fix #2293 - stricter header validity check
1 parent 03a94e3 commit 5dff282

File tree

3 files changed

+40
-13
lines changed

3 files changed

+40
-13
lines changed

mongoose.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1439,11 +1439,11 @@ static bool mg_http_parse_headers(const char *s, const char *end,
14391439
const char *he = skip(s, end, "\r\n", &tmp);
14401440
if (tmp.len == 0) break; // empty header = EOH
14411441
s = skip(s, he, ": \r\n", &k);
1442+
if (k.ptr[k.len] != ':') return false; // Invalid header
14421443
s = skip(s, he, "\r\n", &v);
1443-
if (k.len == tmp.len) continue;
14441444
while (v.len > 0 && v.ptr[v.len - 1] == ' ') v.len--; // Trim spaces
14451445
if (k.len == 0) return false; // empty name
1446-
// MG_INFO(("--HH [%.*s] [%.*s] [%.*s]", (int) tmp.len - 1, tmp.ptr,
1446+
// MG_INFO(("--HH [%.*s] [%.*s] [%.*s]", (int) tmp.len, tmp.ptr,
14471447
//(int) k.len, k.ptr, (int) v.len, v.ptr));
14481448
h[i].name = k;
14491449
h[i].value = v;
@@ -1967,7 +1967,7 @@ static int uri_to_path2(struct mg_connection *c, struct mg_http_message *hm,
19671967
}
19681968
path[path_size - 1] = '\0';
19691969
// Terminate root dir with /
1970-
if (n + 2 < path_size && path[n-1] != '/') path[n++] = '/', path[n] = '\0';
1970+
if (n + 2 < path_size && path[n - 1] != '/') path[n++] = '/', path[n] = '\0';
19711971
mg_url_decode(hm->uri.ptr + url.len, hm->uri.len - url.len, path + n,
19721972
path_size - n, 0);
19731973
path[path_size - 1] = '\0'; // Double-check

src/http.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
#include "http.h"
21
#include "arch.h"
32
#include "base64.h"
43
#include "fmt.h"
4+
#include "http.h"
55
#include "json.h"
66
#include "log.h"
77
#include "net.h"
@@ -207,11 +207,11 @@ static bool mg_http_parse_headers(const char *s, const char *end,
207207
const char *he = skip(s, end, "\r\n", &tmp);
208208
if (tmp.len == 0) break; // empty header = EOH
209209
s = skip(s, he, ": \r\n", &k);
210+
if (k.ptr[k.len] != ':') return false; // Invalid header
210211
s = skip(s, he, "\r\n", &v);
211-
if (k.len == tmp.len) continue;
212212
while (v.len > 0 && v.ptr[v.len - 1] == ' ') v.len--; // Trim spaces
213213
if (k.len == 0) return false; // empty name
214-
// MG_INFO(("--HH [%.*s] [%.*s] [%.*s]", (int) tmp.len - 1, tmp.ptr,
214+
// MG_INFO(("--HH [%.*s] [%.*s] [%.*s]", (int) tmp.len, tmp.ptr,
215215
//(int) k.len, k.ptr, (int) v.len, v.ptr));
216216
h[i].name = k;
217217
h[i].value = v;
@@ -735,7 +735,7 @@ static int uri_to_path2(struct mg_connection *c, struct mg_http_message *hm,
735735
}
736736
path[path_size - 1] = '\0';
737737
// Terminate root dir with /
738-
if (n + 2 < path_size && path[n-1] != '/') path[n++] = '/', path[n] = '\0';
738+
if (n + 2 < path_size && path[n - 1] != '/') path[n++] = '/', path[n] = '\0';
739739
mg_url_decode(hm->uri.ptr + url.len, hm->uri.len - url.len, path + n,
740740
path_size - n, 0);
741741
path[path_size - 1] = '\0'; // Double-check

test/unit_test.c

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,9 @@ static void test_http_server(void) {
845845
ASSERT(fetch(&mgr, buf, url, "GET /a.txt HTTP/1.0\n\n") == 200);
846846
ASSERT(cmpbody(buf, "hello\n") == 0);
847847

848+
// Invalid header: failure
849+
ASSERT(fetch(&mgr, buf, url, "GET /a.txt HTTP/1.0\nA B\n\n") == 0);
850+
848851
ASSERT(fetch(&mgr, buf, url, "GET /%%61.txt HTTP/1.0\n\n") == 200);
849852
ASSERT(cmpbody(buf, "hello\n") == 0);
850853

@@ -1351,16 +1354,40 @@ static void test_http_parse(void) {
13511354
}
13521355

13531356
{
1354-
static const char *s = "get b c\nz : k \nb: t\nvvv\n\n xx";
1357+
const char *s = "get b c\nb: t\nv:vv\n\n xx";
1358+
ASSERT(mg_http_parse(s, strlen(s), &req) == (int) strlen(s) - 3);
1359+
}
1360+
1361+
{
1362+
const char *s = "get b c\nb: t\nv:\n\n xx";
1363+
ASSERT(mg_http_parse(s, strlen(s), &req) == (int) strlen(s) - 3);
1364+
}
1365+
1366+
{
1367+
const char *s = "get b c\nb: t\nv v\n\n xx";
1368+
ASSERT(mg_http_parse(s, strlen(s), &req) == -1);
1369+
}
1370+
1371+
{
1372+
const char *s = "get b c\nb: t\n : aa\n\n";
1373+
ASSERT(mg_http_parse(s, strlen(s), &req) == -1);
1374+
}
1375+
1376+
{
1377+
const char *s = "get b c\nz: k \nb: t\nv:k\n\n xx";
13551378
ASSERT(mg_http_parse(s, strlen(s), &req) == (int) strlen(s) - 3);
1356-
ASSERT(req.headers[2].name.len == 0);
1379+
ASSERT(req.headers[3].name.len == 0);
1380+
ASSERT(mg_vcmp(&req.headers[0].name, "z") == 0);
13571381
ASSERT(mg_vcmp(&req.headers[0].value, "k") == 0);
1382+
ASSERT(mg_vcmp(&req.headers[1].name, "b") == 0);
13581383
ASSERT(mg_vcmp(&req.headers[1].value, "t") == 0);
1384+
ASSERT(mg_vcmp(&req.headers[2].name, "v") == 0);
1385+
ASSERT(mg_vcmp(&req.headers[2].value, "k") == 0);
13591386
ASSERT(req.body.len == 0);
13601387
}
13611388

13621389
{
1363-
const char *s = "a b c\r\nContent-Length: 21 \r\nb: t\r\nvvv\r\n\r\nabc";
1390+
const char *s = "a b c\r\nContent-Length: 21 \r\nb: t\r\nv:v\r\n\r\nabc";
13641391
ASSERT(mg_http_parse(s, strlen(s), &req) == (int) strlen(s) - 3);
13651392
ASSERT(req.body.len == 21);
13661393
ASSERT(req.message.len == 21 - 3 + strlen(s));
@@ -1452,9 +1479,9 @@ static void test_http_parse(void) {
14521479
struct mg_http_message hm;
14531480
const char *s = "a b c\n\n";
14541481
ASSERT(mg_http_parse(s, strlen(s), &hm) == (int) strlen(s));
1455-
s = "a b\nc\n\n";
1482+
s = "a b\nc:d\n\n";
14561483
ASSERT(mg_http_parse(s, strlen(s), &hm) == (int) strlen(s));
1457-
s = "a\nb\nc\n\n";
1484+
s = "a\nb:b\nc:c\n\n";
14581485
ASSERT(mg_http_parse(s, strlen(s), &hm) < 0);
14591486
}
14601487
}
@@ -1922,7 +1949,7 @@ static void test_str(void) {
19221949

19231950
static void fn1(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
19241951
if (ev == MG_EV_ERROR) {
1925-
ASSERT(* (void **) fn_data == NULL);
1952+
ASSERT(*(void **) fn_data == NULL);
19261953
*(char **) fn_data = mg_mprintf("%s", (char *) ev_data);
19271954
}
19281955
(void) c;

0 commit comments

Comments
 (0)