diff --git a/mongoose.c b/mongoose.c index 2801a185e2..ca6ef32b48 100644 --- a/mongoose.c +++ b/mongoose.c @@ -1976,15 +1976,17 @@ static int uri_to_path2(struct mg_connection *c, struct mg_http_message *hm, int flags, tmp; // Append URI to the root_dir, and sanitize it size_t n = mg_snprintf(path, path_size, "%.*s", (int) dir.len, dir.ptr); - if (n > path_size) { + if (n + 2 >= path_size) { mg_http_reply(c, 400, "", "Exceeded path size"); return -1; } path[path_size - 1] = '\0'; - // Terminate root dir with / - if (n + 2 < path_size && path[n - 1] != '/') path[n++] = '/', path[n] = '\0'; - mg_url_decode(hm->uri.ptr + url.len, hm->uri.len - url.len, path + n, - path_size - n, 0); + // Terminate root dir with slash + if (n > 0 && path[n - 1] != '/') path[n++] = '/', path[n] = '\0'; + if (url.len < hm->uri.len) { + mg_url_decode(hm->uri.ptr + url.len, hm->uri.len - url.len, path + n, + path_size - n, 0); + } path[path_size - 1] = '\0'; // Double-check if (!mg_path_is_sane(path)) { mg_http_reply(c, 400, "", "Invalid path"); @@ -2033,7 +2035,7 @@ static int uri_to_path(struct mg_connection *c, struct mg_http_message *hm, struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs; struct mg_str k, v, s = mg_str(opts->root_dir), u = {0, 0}, p = {0, 0}; while (mg_commalist(&s, &k, &v)) { - if (v.len == 0) v = k, k = mg_str("/"); + if (v.len == 0) v = k, k = mg_str("/"), u = k, p = v; if (hm->uri.len < k.len) continue; if (mg_strcmp(k, mg_str_n(hm->uri.ptr, k.len)) != 0) continue; u = k, p = v; @@ -2274,7 +2276,6 @@ static void deliver_normal_chunks(struct mg_connection *c, size_t hlen, static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) { if (ev == MG_EV_READ || ev == MG_EV_CLOSE) { struct mg_http_message hm; - // mg_hexdump(c->recv.buf, c->recv.len); while (c->recv.buf != NULL && c->recv.len > 0) { bool next = false; int hlen = mg_http_parse((char *) c->recv.buf, c->recv.len, &hm); @@ -8906,7 +8907,7 @@ static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) { rx_ip(ifp, &pkt); } else { MG_DEBUG(("Unknown eth type %x", mg_htons(pkt.eth->type))); - mg_hexdump(buf, len >= 32 ? 32 : len); + //mg_hexdump(buf, len >= 32 ? 32 : len); } } diff --git a/src/http.c b/src/http.c index 113dad621c..7abe4702c4 100644 --- a/src/http.c +++ b/src/http.c @@ -744,15 +744,17 @@ static int uri_to_path2(struct mg_connection *c, struct mg_http_message *hm, int flags, tmp; // Append URI to the root_dir, and sanitize it size_t n = mg_snprintf(path, path_size, "%.*s", (int) dir.len, dir.ptr); - if (n > path_size) { + if (n + 2 >= path_size) { mg_http_reply(c, 400, "", "Exceeded path size"); return -1; } path[path_size - 1] = '\0'; - // Terminate root dir with / - if (n + 2 < path_size && path[n - 1] != '/') path[n++] = '/', path[n] = '\0'; - mg_url_decode(hm->uri.ptr + url.len, hm->uri.len - url.len, path + n, - path_size - n, 0); + // Terminate root dir with slash + if (n > 0 && path[n - 1] != '/') path[n++] = '/', path[n] = '\0'; + if (url.len < hm->uri.len) { + mg_url_decode(hm->uri.ptr + url.len, hm->uri.len - url.len, path + n, + path_size - n, 0); + } path[path_size - 1] = '\0'; // Double-check if (!mg_path_is_sane(path)) { mg_http_reply(c, 400, "", "Invalid path"); @@ -801,7 +803,7 @@ static int uri_to_path(struct mg_connection *c, struct mg_http_message *hm, struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs; struct mg_str k, v, s = mg_str(opts->root_dir), u = {0, 0}, p = {0, 0}; while (mg_commalist(&s, &k, &v)) { - if (v.len == 0) v = k, k = mg_str("/"); + if (v.len == 0) v = k, k = mg_str("/"), u = k, p = v; if (hm->uri.len < k.len) continue; if (mg_strcmp(k, mg_str_n(hm->uri.ptr, k.len)) != 0) continue; u = k, p = v; @@ -1042,7 +1044,6 @@ static void deliver_normal_chunks(struct mg_connection *c, size_t hlen, static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) { if (ev == MG_EV_READ || ev == MG_EV_CLOSE) { struct mg_http_message hm; - // mg_hexdump(c->recv.buf, c->recv.len); while (c->recv.buf != NULL && c->recv.len > 0) { bool next = false; int hlen = mg_http_parse((char *) c->recv.buf, c->recv.len, &hm); diff --git a/src/tcpip/tcpip.c b/src/tcpip/tcpip.c index a0078f87b7..caca5e2b42 100644 --- a/src/tcpip/tcpip.c +++ b/src/tcpip/tcpip.c @@ -796,7 +796,7 @@ static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) { rx_ip(ifp, &pkt); } else { MG_DEBUG(("Unknown eth type %x", mg_htons(pkt.eth->type))); - mg_hexdump(buf, len >= 32 ? 32 : len); + //mg_hexdump(buf, len >= 32 ? 32 : len); } } diff --git a/test/fuzz.c b/test/fuzz.c index adb4939889..b4c8a3d1ae 100644 --- a/test/fuzz.c +++ b/test/fuzz.c @@ -13,6 +13,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *, size_t); int LLVMFuzzerTestOneInput(const uint8_t *, size_t); #endif +static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { + struct mg_http_serve_opts opts = {.root_dir = "."}; + if (ev == MG_EV_HTTP_MSG) { + mg_http_serve_dir(c, (struct mg_http_message *) ev_data, &opts); + } + (void) fn_data; +} + int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { mg_log_set(MG_LL_NONE); @@ -96,6 +104,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { } mg_tcpip_rx(&mif, pkt, size); + + // Test HTTP serving + const char *url = "http://localhost:12345"; + struct mg_connection *c = mg_http_connect(&mgr, url, fn, NULL); + mg_iobuf_add(&c->recv, 0, data, size); + c->pfn(c, MG_EV_READ, NULL, NULL); + mg_mgr_free(&mgr); free(pkt); mg_tcpip_free(&mif); diff --git a/test/unit_test.c b/test/unit_test.c index 82ffcf649e..91e32ed09d 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -134,21 +134,26 @@ static void test_commalist(void) { struct mg_str s4 = mg_str("a=123"), s5 = mg_str("a,b=123"); ASSERT(mg_commalist(&s1, &k, &v) == false); + v.len = k.len = 42; ASSERT(mg_commalist(&s2, &k, &v) == true); ASSERT(v.len == 0 && mg_vcmp(&k, "a") == 0); ASSERT(mg_commalist(&s2, &k, &v) == false); + v.len = k.len = 42; ASSERT(mg_commalist(&s3, &k, &v) == true); ASSERT(v.len == 0 && mg_vcmp(&k, "a") == 0); + v.len = k.len = 42; ASSERT(mg_commalist(&s3, &k, &v) == true); ASSERT(v.len == 0 && mg_vcmp(&k, "b") == 0); ASSERT(mg_commalist(&s3, &k, &v) == false); + v.len = k.len = 42; ASSERT(mg_commalist(&s4, &k, &v) == true); ASSERT(mg_vcmp(&k, "a") == 0 && mg_vcmp(&v, "123") == 0); ASSERT(mg_commalist(&s4, &k, &v) == false); ASSERT(mg_commalist(&s4, &k, &v) == false); + v.len = k.len = 42; ASSERT(mg_commalist(&s5, &k, &v) == true); ASSERT(v.len == 0 && mg_vcmp(&k, "a") == 0); ASSERT(mg_commalist(&s5, &k, &v) == true);