From e7c34c26cbd0f9b665a829fc8632bf3d2af68af3 Mon Sep 17 00:00:00 2001
From: Sergey Lyubka <valenok@gmail.com>
Date: Mon, 1 Jul 2013 08:45:07 +0100
Subject: [PATCH] mg_read() with no Content-Length would read until socket is
 closed

---
 mongoose.c       | 14 +++++++++++++-
 test/unit_test.c | 14 ++++++++++++--
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/mongoose.c b/mongoose.c
index 1293836b4..74e0b45cb 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 e6303d993..65bfd4bd4 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",
-- 
GitLab