Ver Fonte

Merge commit from fork

* fix(parser): Limit line length in getline

Prevents potential infinite loop and memory exhaustion in
stream_line_reader::getline by enforcing max line length.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>

* fix: increase default max line length to 32k

LONG_QUERY_VALUE test is set at 25k.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>

* test(client): expect read error with too long query

Adds a test case (`TooLongQueryValue`) to verify client behavior
when the request URI is excessively long, exceeding
`CPPHTTPLIB_MAX_LINE_LENGTH`. In this scenario, the server is
expected to reset the connection.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>

---------

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
Ville Vesilehto há 9 meses atrás
pai
commit
7b752106ac
2 ficheiros alterados com 24 adições e 0 exclusões
  1. 9 0
      httplib.h
  2. 15 0
      test/test.cc

+ 9 - 0
httplib.h

@@ -145,6 +145,10 @@
 #define CPPHTTPLIB_LISTEN_BACKLOG 5
 #endif
 
+#ifndef CPPHTTPLIB_MAX_LINE_LENGTH
+#define CPPHTTPLIB_MAX_LINE_LENGTH 32768
+#endif
+
 /*
  * Headers
  */
@@ -3067,6 +3071,11 @@ inline bool stream_line_reader::getline() {
 #endif
 
   for (size_t i = 0;; i++) {
+    if (size() >= CPPHTTPLIB_MAX_LINE_LENGTH) {
+      // Treat exceptionally long lines as an error to
+      // prevent infinite loops/memory exhaustion
+      return false;
+    }
     char byte;
     auto n = strm_.read(&byte, 1);
 

+ 15 - 0
test/test.cc

@@ -43,6 +43,9 @@ const int PORT = 1234;
 const string LONG_QUERY_VALUE = string(25000, '@');
 const string LONG_QUERY_URL = "/long-query-value?key=" + LONG_QUERY_VALUE;
 
+const string TOO_LONG_QUERY_VALUE = string(35000, '@');
+const string TOO_LONG_QUERY_URL = "/too-long-query-value?key=" + TOO_LONG_QUERY_VALUE;
+
 const std::string JSON_DATA = "{\"hello\":\"world\"}";
 
 const string LARGE_DATA = string(1024 * 1024 * 100, '@'); // 100MB
@@ -2867,6 +2870,11 @@ protected:
                EXPECT_EQ(LONG_QUERY_URL, req.target);
                EXPECT_EQ(LONG_QUERY_VALUE, req.get_param_value("key"));
              })
+        .Get("/too-long-query-value",
+             [&](const Request &req, Response & /*res*/) {
+               EXPECT_EQ(TOO_LONG_QUERY_URL, req.target);
+               EXPECT_EQ(TOO_LONG_QUERY_VALUE, req.get_param_value("key"));
+             })
         .Get("/array-param",
              [&](const Request &req, Response & /*res*/) {
                EXPECT_EQ(3u, req.get_param_value_count("array"));
@@ -3655,6 +3663,13 @@ TEST_F(ServerTest, LongQueryValue) {
   EXPECT_EQ(StatusCode::UriTooLong_414, res->status);
 }
 
+TEST_F(ServerTest, TooLongQueryValue) {
+  auto res = cli_.Get(TOO_LONG_QUERY_URL.c_str());
+
+  ASSERT_FALSE(res);
+  EXPECT_EQ(Error::Read, res.error());
+}
+
 TEST_F(ServerTest, TooLongHeader) {
   Request req;
   req.method = "GET";