diff --git a/httplib.h b/httplib.h index cb182c4..a2aa24f 100644 --- a/httplib.h +++ b/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); diff --git a/test/test.cc b/test/test.cc index 4fd9983..7f5cc8a 100644 --- a/test/test.cc +++ b/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";