diff --git a/proxy/hdrs/HTTP.cc b/proxy/hdrs/HTTP.cc index 319745420ef..56a71c36f2c 100644 --- a/proxy/hdrs/HTTP.cc +++ b/proxy/hdrs/HTTP.cc @@ -27,6 +27,7 @@ #include #include #include +#include #include "HTTP.h" #include "HdrToken.h" #include "tscore/Diags.h" @@ -1261,26 +1262,27 @@ validate_hdr_content_length(HdrHeap *heap, HTTPHdrImpl *hh) // recipient MUST treat it as an unrecoverable error. If this is a // request message, the server MUST respond with a 400 (Bad Request) // status code and then close the connection - int content_length_len = 0; - const char *content_length_val = content_length_field->value_get(&content_length_len); + std::string_view value = content_length_field->value_get(); - // RFC 7230 section 3.3.2 + // RFC 9110 section 8.6. // Content-Length = 1*DIGIT // + if (value.empty()) { + Debug("http", "Content-Length headers don't match the ABNF, returning parse error"); + return PARSE_RESULT_ERROR; + } + // If the content-length value contains a non-numeric value, the header is invalid - for (int i = 0; i < content_length_len; i++) { - if (!isdigit(content_length_val[i])) { - Debug("http", "Content-Length value contains non-digit, returning parse error"); - return PARSE_RESULT_ERROR; - } + if (std::find_if(value.cbegin(), value.cend(), [](std::string_view::value_type c) { return !std::isdigit(c); }) != + value.cend()) { + Debug("http", "Content-Length value contains non-digit, returning parse error"); + return PARSE_RESULT_ERROR; } while (content_length_field->has_dups()) { - int content_length_len_2 = 0; - const char *content_length_val_2 = content_length_field->m_next_dup->value_get(&content_length_len_2); + std::string_view value_dup = content_length_field->m_next_dup->value_get(); - if ((content_length_len != content_length_len_2) || - (memcmp(content_length_val, content_length_val_2, content_length_len) != 0)) { + if ((value.length() != value_dup.length()) || value.compare(value_dup) != 0) { // Values are different, parse error Debug("http", "Content-Length headers don't match, returning parse error"); return PARSE_RESULT_ERROR; diff --git a/proxy/hdrs/unit_tests/test_Hdrs.cc b/proxy/hdrs/unit_tests/test_Hdrs.cc index ca79badc52d..4f70c2d063d 100644 --- a/proxy/hdrs/unit_tests/test_Hdrs.cc +++ b/proxy/hdrs/unit_tests/test_Hdrs.cc @@ -46,7 +46,7 @@ TEST_CASE("HdrTestHttpParse", "[proxy][hdrtest]") int expected_result; int expected_bytes_consumed; }; - static const std::array tests = { + static const std::array tests = { { {"GET /index.html HTTP/1.0\r\n", PARSE_RESULT_DONE, 26}, {"GET /index.html HTTP/1.0\r\n\r\n***BODY****", PARSE_RESULT_DONE, 28}, @@ -68,6 +68,9 @@ TEST_CASE("HdrTestHttpParse", "[proxy][hdrtest]") {"GET /index.html HTTP/1.0\r\nUser-Agent: foobar\r\n", PARSE_RESULT_DONE, 46}, {"GET /index.html HTTP/1.0\r\n", PARSE_RESULT_DONE, 26}, {"GET /index.html hTTP/1.0\r\n", PARSE_RESULT_ERROR, 26}, + {"POST /index.html HTTP/1.0\r\nContent-Length: 0\r\n\r\n", PARSE_RESULT_DONE, 48}, + {"POST /index.html HTTP/1.0\r\nContent-Length: \r\n\r\n", PARSE_RESULT_ERROR, 47}, + {"POST /index.html HTTP/1.0\r\nContent-Length:\r\n\r\n", PARSE_RESULT_ERROR, 46}, {"CONNECT foo.example HTTP/1.1\r\n", PARSE_RESULT_DONE, 30}, {"GET foo.example HTTP/1.1\r\n", PARSE_RESULT_ERROR, 26}, {"", PARSE_RESULT_ERROR, 0},