From e5cacb465d3086c7d9be1d87dfffedbafeb02ce8 Mon Sep 17 00:00:00 2001 From: yhirose Date: Wed, 26 Jan 2022 13:34:23 -0500 Subject: [PATCH] Fix #1172 (#1173) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change is based on RFC7230, ยง 3.5 'Message Parsing Robustness': "Although the line terminator for the start-line and header fields is the sequence CRLF, a recipient MAY recognize a single LF as a line terminator and ignore any preceding CR." --- httplib.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/httplib.h b/httplib.h index b5e1e0f..38c88ab 100644 --- a/httplib.h +++ b/httplib.h @@ -3217,17 +3217,26 @@ inline bool read_headers(Stream &strm, Headers &headers) { if (!line_reader.getline()) { return false; } // Check if the line ends with CRLF. + auto line_terminator_len = 2; if (line_reader.end_with_crlf()) { // Blank line indicates end of headers. if (line_reader.size() == 2) { break; } +#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR + } else { + // Blank line indicates end of headers. + if (line_reader.size() == 1) { break; } + line_terminator_len = 1; + } +#else } else { continue; // Skip invalid line. } +#endif if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; } - // Exclude CRLF - auto end = line_reader.ptr() + line_reader.size() - 2; + // Exclude line terminator + auto end = line_reader.ptr() + line_reader.size() - line_terminator_len; parse_header(line_reader.ptr(), end, [&](std::string &&key, std::string &&val) { @@ -5837,7 +5846,11 @@ inline bool ClientImpl::read_response_line(Stream &strm, const Request &req, if (!line_reader.getline()) { return false; } +#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR const static std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r\n"); +#else + const static std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r?\n"); +#endif std::cmatch m; if (!std::regex_match(line_reader.ptr(), m, re)) {