]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
content_encoding: reject transfer-encoding after chunked
authorStefan Eissing <stefan@eissing.org>
Tue, 21 May 2024 09:38:47 +0000 (11:38 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 21 May 2024 13:06:41 +0000 (15:06 +0200)
reject a response that applies a transfer-encoding after a 'chunked'
encoding. RFC 9112 ch. 6.1 required chunked to be the final encoding.

Closes #13733

lib/content_encoding.c

index 13b21dfa50785df1513c84c371c8eba81de1a1d0..d34d3a1f5e265a4205af21ad5708e48143cd91a0 100644 (file)
@@ -978,6 +978,7 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
   do {
     const char *name;
     size_t namelen;
+    bool is_chunked = FALSE;
 
     /* Parse a single encoding name. */
     while(ISBLANK(*enclist) || *enclist == ',')
@@ -993,10 +994,11 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
       const struct Curl_cwtype *cwt;
       struct Curl_cwriter *writer;
 
+      is_chunked = (is_transfer && (namelen == 7) &&
+                    strncasecompare(name, "chunked", 7));
       /* if we skip the decoding in this phase, do not look further.
        * Exception is "chunked" transfer-encoding which always must happen */
-      if((is_transfer && !data->set.http_transfer_encoding &&
-          (namelen != 7 || !strncasecompare(name, "chunked", 7))) ||
+      if((is_transfer && !data->set.http_transfer_encoding && !is_chunked) ||
          (!is_transfer && data->set.http_ce_skip)) {
         /* not requested, ignore */
         return CURLE_OK;
@@ -1009,13 +1011,31 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
       }
 
       cwt = find_unencode_writer(name, namelen, phase);
-      if(is_transfer && cwt && strncasecompare(name, "chunked", 7) &&
-         Curl_cwriter_get_by_type(data, cwt)) {
+      if(cwt && is_chunked && Curl_cwriter_get_by_type(data, cwt)) {
         /* A 'chunked' transfer encoding has already been added.
-         * Ignore duplicates. See #13451. */
+         * Ignore duplicates. See #13451.
+         * Also RFC 9112, ch. 6.1:
+         * "A sender MUST NOT apply the chunked transfer coding more than
+         *  once to a message body."
+         */
         return CURLE_OK;
       }
 
+      if(is_transfer && !is_chunked &&
+         Curl_cwriter_get_by_name(data, "chunked")) {
+        /* RFC 9112, ch. 6.1:
+         * "If any transfer coding other than chunked is applied to a
+         *  response's content, the sender MUST either apply chunked as the
+         *  final transfer coding or terminate the message by closing the
+         *  connection."
+         * "chunked" must be the last added to be the first in its phase,
+         *  reject this.
+         */
+        failf(data, "Reject response due to 'chunked' not being the last "
+              "Transfer-Encoding");
+        return CURLE_BAD_CONTENT_ENCODING;
+      }
+
       if(!cwt)
         cwt = &error_writer;  /* Defer error at use. */