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},

Reply via email to