diff --git a/mongoose.c b/mongoose.c index 1293836b490c70bc1baedbd07c7a03fb27a67034..74e0b45cb4809c9a5ea5808f4f84d547196c91b0 100644 --- a/mongoose.c +++ b/mongoose.c @@ -1544,6 +1544,12 @@ int mg_read(struct mg_connection *conn, void *buf, size_t len) { int n, buffered_len, nread; const char *body; + // If Content-Length is not set, read until socket is closed + if (conn->consumed_content == 0 && conn->content_len == 0) { + conn->content_len = INT64_MAX; + conn->must_close = 1; + } + nread = 0; if (conn->consumed_content < conn->content_len) { // Adjust number of bytes to read. @@ -4889,6 +4895,10 @@ static int getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len) { !mg_strcasecmp(conn->request_info.request_method, "PUT")) { conn->content_len = -1; } else { + // Content-Length is not set. Set content_len to maximum possible + // value, instructing mg_read() to read data until socket is closed. + // Message boundary is not known in this case, therefore this + // connection must be closed after conn->content_len = 0; } conn->birth_time = time(NULL); @@ -4951,7 +4961,9 @@ static void process_new_connection(struct mg_connection *conn) { } if (ri->remote_user != NULL) { free((void *) ri->remote_user); - ri->remote_user = NULL; // when having connections with and without auth would cause double free and then crash + // Important! When having connections with and without auth + // would cause double free and then crash + ri->remote_user = NULL; } // NOTE(lsm): order is important here. should_keep_alive() call diff --git a/test/unit_test.c b/test/unit_test.c index e6303d993f7350829e5122e0b237bf742e44b463..65bfd4bd4efceb4e2e86fbfbb74bf4f0f24c760c 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -220,9 +220,9 @@ static int begin_request_handler_cb(struct mg_connection *conn) { if (!strcmp(ri->uri, "/data")) { mg_printf(conn, "HTTP/1.1 200 OK\r\n" - "Content-Length: %d\r\n" "Content-Type: text/plain\r\n\r\n" - "%s", (int) strlen(fetch_data), fetch_data); + "%s", fetch_data); + close_connection(conn); return 1; } @@ -298,6 +298,7 @@ static void test_mg_download(void) { free(p1), free(p2); mg_close_connection(conn); + // Fetch in-memory file, should succeed. ASSERT((conn = mg_download("localhost", port, 1, ebuf, sizeof(ebuf), "%s", "GET /blah HTTP/1.1\r\n\r\n")) != NULL); @@ -307,6 +308,15 @@ static void test_mg_download(void) { free(p1); mg_close_connection(conn); + // Fetch in-memory data with no Content-Length, should succeed. + ASSERT((conn = mg_download("localhost", port, 1, ebuf, sizeof(ebuf), "%s", + "GET /data HTTP/1.1\r\n\r\n")) != NULL); + ASSERT((p1 = read_conn(conn, &len1)) != NULL); + ASSERT(len1 == (int) strlen(fetch_data)); + ASSERT(memcmp(p1, fetch_data, len1) == 0); + free(p1); + mg_close_connection(conn); + // Test SSL redirect, IP address ASSERT((conn = mg_download("localhost", atoi(HTTP_PORT), 0, ebuf, sizeof(ebuf), "%s",