diff --git a/httplib.h b/httplib.h index a49d317..dda2f78 100644 --- a/httplib.h +++ b/httplib.h @@ -1847,7 +1847,7 @@ inline bool read_headers(Stream &strm, Headers &headers) { // the left or right side of the header value: // - https://stackoverflow.com/questions/50179659/ // - https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html - static const std::regex re(R"(([^:]+):[\t ]*(.+))"); + static const std::regex re(R"(([^:]+):[\t ]*([^\t ].*))"); std::cmatch m; if (std::regex_match(line_reader.ptr(), end, m, re)) { diff --git a/test/test.cc b/test/test.cc index 9945153..a9dcdbd 100644 --- a/test/test.cc +++ b/test/test.cc @@ -2333,6 +2333,19 @@ TEST(ServerRequestParsingTest, ReadHeadersRegexComplexity2) { "&&&%%%"); } +TEST(ServerRequestParsingTest, ExcessiveWhitespaceInUnparseableHeaderLine) { + // Make sure this doesn't crash the server. + // In a previous version of the header line regex, the "\r" rendered the line + // unparseable and the regex engine repeatedly backtracked, trying to look for + // a new position where the leading white space ended and the field value + // began. + // The crash occurs with libc++ but not libstdc++. + test_raw_request("GET /hi HTTP/1.1\r\n" + "a:" + std::string(2000, ' ') + '\r' + std::string(20, 'z') + + "\r\n" + "\r\n"); +} + TEST(ServerRequestParsingTest, InvalidFirstChunkLengthInRequest) { std::string out;