This is an automated email from the ASF dual-hosted git repository.
masaori pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new f9aa1e0adb Strictly follow Content-Length header ABNF rule (#10144)
f9aa1e0adb is described below
commit f9aa1e0adb7d23cb9d9dd4fb421b80a24654ae85
Author: Masaori Koshiba <[email protected]>
AuthorDate: Mon Aug 7 11:52:34 2023 +0900
Strictly follow Content-Length header ABNF rule (#10144)
- Replace content-length value type from const char * to std::string_view
---
proxy/hdrs/HTTP.cc | 26 ++++++++++++++------------
proxy/hdrs/unit_tests/test_Hdrs.cc | 5 ++++-
2 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/proxy/hdrs/HTTP.cc b/proxy/hdrs/HTTP.cc
index 319745420e..56a71c36f2 100644
--- a/proxy/hdrs/HTTP.cc
+++ b/proxy/hdrs/HTTP.cc
@@ -27,6 +27,7 @@
#include <cassert>
#include <cstdio>
#include <cstring>
+#include <string_view>
#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 ca79badc52..4f70c2d063 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<Test, 23> tests = {
+ static const std::array<Test, 26> 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},