Blame SOURCES/0024-curl-7.76.1-CVE-2023-23916.patch

4118ca
From 95f873ff983a1ae57415b3c16a881e74432cf8b8 Mon Sep 17 00:00:00 2001
4118ca
From: Fabian Keil <fk@fabiankeil.de>
4118ca
Date: Tue, 9 Feb 2021 14:04:32 +0100
4118ca
Subject: [PATCH 1/4] runtests.pl: support the nonewline attribute for the data
4118ca
 part
4118ca
4118ca
Added to FILEFORMAT
4118ca
4118ca
Closes #8239
4118ca
4118ca
Upstream-commit: 736847611a40c01e7c290407e22e2f0f5f8efd6a
4118ca
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
4118ca
---
4118ca
 tests/FILEFORMAT.md    |  5 ++++-
4118ca
 tests/runtests.pl      |  7 +++++++
4118ca
 tests/server/getpart.c | 11 ++++++++++-
4118ca
 3 files changed, 21 insertions(+), 2 deletions(-)
4118ca
4118ca
diff --git a/tests/FILEFORMAT.md b/tests/FILEFORMAT.md
4118ca
index b75a02a..0b98787 100644
4118ca
--- a/tests/FILEFORMAT.md
4118ca
+++ b/tests/FILEFORMAT.md
4118ca
@@ -185,7 +185,7 @@ which are treated together as a single identifier.
4118ca
 
4118ca
 ## `<reply>`
4118ca
 
4118ca
-### `<data [nocheck="yes"] [sendzero="yes"] [base64="yes"] [hex="yes"]>`
4118ca
+### `<data [nocheck="yes"] [sendzero="yes"] [base64="yes"] [hex="yes"] [nonewline="yes"]>`
4118ca
 
4118ca
 data to be sent to the client on its request and later verified that it
4118ca
 arrived safely. Set `nocheck="yes"` to prevent the test script from verifying
4118ca
@@ -211,6 +211,9 @@ much sense for other sections than "data").
4118ca
 `hex=yes` means that the data is a sequence of hex pairs. It will get decoded
4118ca
 and used as "raw" data.
4118ca
 
4118ca
+`nonewline=yes` means that the last byte (the trailing newline character)
4118ca
+should be cut off from the data before sending or comparing it.
4118ca
+
4118ca
 For FTP file listings, the `<data>` section will be used *only* if you make
4118ca
 sure that there has been a CWD done first to a directory named `test-[num]`
4118ca
 where [num] is the test case number. Otherwise the ftp server can't know from
4118ca
diff --git a/tests/runtests.pl b/tests/runtests.pl
4118ca
index 40315aa..2e1500d 100755
4118ca
--- a/tests/runtests.pl
4118ca
+++ b/tests/runtests.pl
4118ca
@@ -3837,6 +3837,13 @@ sub singletest {
4118ca
     else {
4118ca
         # check against the data section
4118ca
         @reply = getpart("reply", "data");
4118ca
+        if(@reply) {
4118ca
+            my %hash = getpartattr("reply", "data");
4118ca
+            if($hash{'nonewline'}) {
4118ca
+                # cut off the final newline from the final line of the data
4118ca
+                chomp($reply[$#reply]);
4118ca
+            }
4118ca
+        }
4118ca
         # get the mode attribute
4118ca
         my $filemode=$replyattr{'mode'};
4118ca
         if($filemode && ($filemode eq "text") && $has_textaware) {
4118ca
diff --git a/tests/server/getpart.c b/tests/server/getpart.c
4118ca
index 32b55bc..f8fe3f6 100644
4118ca
--- a/tests/server/getpart.c
4118ca
+++ b/tests/server/getpart.c
4118ca
@@ -5,7 +5,7 @@
4118ca
  *                            | (__| |_| |  _ <| |___
4118ca
  *                             \___|\___/|_| \_\_____|
4118ca
  *
4118ca
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
4118ca
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
4118ca
  *
4118ca
  * This software is licensed as described in the file COPYING, which
4118ca
  * you should have received as part of this distribution. The terms
4118ca
@@ -295,6 +295,7 @@ int getpart(char **outbuf, size_t *outlen,
4118ca
   size_t outalloc = 256;
4118ca
   int in_wanted_part = 0;
4118ca
   int base64 = 0;
4118ca
+  int nonewline = 0;
4118ca
   int error;
4118ca
 
4118ca
   enum {
4118ca
@@ -360,6 +361,8 @@ int getpart(char **outbuf, size_t *outlen,
4118ca
             if(error)
4118ca
               return error;
4118ca
           }
4118ca
+          if(nonewline)
4118ca
+            (*outlen)--;
4118ca
           break;
4118ca
         }
4118ca
       }
4118ca
@@ -377,6 +380,8 @@ int getpart(char **outbuf, size_t *outlen,
4118ca
             if(error)
4118ca
               return error;
4118ca
           }
4118ca
+          if(nonewline)
4118ca
+            (*outlen)--;
4118ca
           break;
4118ca
         }
4118ca
       }
4118ca
@@ -451,6 +456,10 @@ int getpart(char **outbuf, size_t *outlen,
4118ca
               /* bit rough test, but "mostly" functional, */
4118ca
               /* treat wanted part data as base64 encoded */
4118ca
               base64 = 1;
4118ca
+          if(strstr(patt, "nonewline=")) {
4118ca
+            show(("* setting nonewline\n"));
4118ca
+            nonewline = 1;
4118ca
+          }
4118ca
         }
4118ca
         continue;
4118ca
       }
4118ca
-- 
4118ca
2.39.1
4118ca
4118ca
4118ca
From 6e244e1bcb04012e11c537253e76e6f968d8bb72 Mon Sep 17 00:00:00 2001
4118ca
From: Daniel Stenberg <daniel@haxx.se>
4118ca
Date: Thu, 1 Dec 2022 09:21:04 +0100
4118ca
Subject: [PATCH 2/4] runtests: do CRLF replacements per section only
4118ca
4118ca
The `crlf="yes"` attribute and "hyper mode" are now only applied on a
4118ca
subset of dedicated sections: data, datacheck, stdout and protocol.
4118ca
4118ca
Updated test 2500 accordingly.
4118ca
4118ca
Also made test1 use crlf="yes" for <protocol>, mostly because it is
4118ca
often used as a template test case. Going forward, using this attribute
4118ca
we should be able to write test cases using linefeeds only and avoid
4118ca
mixed line ending encodings.
4118ca
4118ca
Follow-up to ca15b7512e8d11
4118ca
4118ca
Fixes #10009
4118ca
Closes #10010
4118ca
4118ca
Upstream-commit: 2f34a7347f315513bfda9ef14770d287fb246bcd
4118ca
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
4118ca
---
4118ca
 tests/FILEFORMAT.md | 22 +++++++++++++++------
4118ca
 tests/data/test1    | 14 ++++++-------
4118ca
 tests/runtests.pl   | 48 ++++++++++++++++++++++++++++++++++++++++++---
4118ca
 3 files changed, 68 insertions(+), 16 deletions(-)
4118ca
4118ca
diff --git a/tests/FILEFORMAT.md b/tests/FILEFORMAT.md
4118ca
index c1fbc57..dcb5695 100644
4118ca
--- a/tests/FILEFORMAT.md
4118ca
+++ b/tests/FILEFORMAT.md
4118ca
@@ -185,7 +185,7 @@ which are treated together as a single identifier.
4118ca
 
4118ca
 ## `<reply>`
4118ca
 
4118ca
-### `<data [nocheck="yes"] [sendzero="yes"] [base64="yes"] [hex="yes"] [nonewline="yes"]>`
4118ca
+### `<data [nocheck="yes"] [sendzero="yes"] [base64="yes"] [hex="yes"] [nonewline="yes"] [crlf="yes"]>`
4118ca
 
4118ca
 data to be sent to the client on its request and later verified that it
4118ca
 arrived safely. Set `nocheck="yes"` to prevent the test script from verifying
4118ca
@@ -214,12 +214,16 @@ and used as "raw" data.
4118ca
 `nonewline=yes` means that the last byte (the trailing newline character)
4118ca
 should be cut off from the data before sending or comparing it.
4118ca
 
4118ca
+`crlf=yes` forces *header* newlines to become CRLF even if not written so in
4118ca
+the source file. Note that this makes runtests.pl parse and "guess" what is a
4118ca
+header and what is not in order to apply the CRLF line endings appropriately.
4118ca
+
4118ca
 For FTP file listings, the `<data>` section will be used *only* if you make
4118ca
 sure that there has been a CWD done first to a directory named `test-[num]`
4118ca
 where [num] is the test case number. Otherwise the ftp server can't know from
4118ca
 which test file to load the list content.
4118ca
 
4118ca
-### `<dataNUM>`
4118ca
+### `<dataNUM [crlf="yes"]>`
4118ca
 
4118ca
 Send back this contents instead of the <data> one. The num is set by:
4118ca
 
4118ca
@@ -243,7 +247,7 @@ The connect section is used instead of the 'data' for all CONNECT
4118ca
 requests. The remainder of the rules for the data section then apply but with
4118ca
 a connect prefix.
4118ca
 
4118ca
-### `<datacheck [mode="text"] [nonewline="yes"]>`
4118ca
+### `<datacheck [mode="text"] [nonewline="yes"] [crlf="yes"]>`
4118ca
 if the data is sent but this is what should be checked afterwards. If
4118ca
 `nonewline=yes` is set, runtests will cut off the trailing newline from the
4118ca
 data before comparing with the one actually received by the client.
4118ca
@@ -251,7 +255,7 @@ data before comparing with the one actually received by the client.
4118ca
 Use the `mode="text"` attribute if the output is in text mode on platforms
4118ca
 that have a text/binary difference.
4118ca
 
4118ca
-### `<datacheckNUM [nonewline="yes"] [mode="text"]>`
4118ca
+### `<datacheckNUM [nonewline="yes"] [mode="text"] [crlf="yes"]>`
4118ca
 The contents of numbered datacheck sections are appended to the non-numbered
4118ca
 one.
4118ca
 
4118ca
@@ -528,13 +532,16 @@ changing protocol data such as port numbers or user-agent strings.
4118ca
 One perl op per line that operates on the protocol dump. This is pretty
4118ca
 advanced. Example: `s/^EPRT .*/EPRT stripped/`.
4118ca
 
4118ca
-### `<protocol [nonewline="yes"]>`
4118ca
+### `<protocol [nonewline="yes"] crlf="yes">`
4118ca
 
4118ca
 the protocol dump curl should transmit, if 'nonewline' is set, we will cut off
4118ca
 the trailing newline of this given data before comparing with the one actually
4118ca
 sent by the client The `<strip>` and `<strippart>` rules are applied before
4118ca
 comparisons are made.
4118ca
 
4118ca
+`crlf=yes` forces the newlines to become CRLF even if not written so in the
4118ca
+test.
4118ca
+
4118ca
 ### `<proxy [nonewline="yes"]>`
4118ca
 
4118ca
 The protocol dump curl should transmit to a HTTP proxy (when the http-proxy
4118ca
@@ -551,7 +558,7 @@ have a text/binary difference.
4118ca
 If 'nonewline' is set, we will cut off the trailing newline of this given data
4118ca
 before comparing with the one actually received by the client
4118ca
 
4118ca
-### `<stdout [mode="text"] [nonewline="yes"]>`
4118ca
+### `<stdout [mode="text"] [nonewline="yes"] [crlf="yes"]>`
4118ca
 This verifies that this data was passed to stdout.
4118ca
 
4118ca
 Use the mode="text" attribute if the output is in text mode on platforms that
4118ca
@@ -560,6 +567,9 @@ have a text/binary difference.
4118ca
 If 'nonewline' is set, we will cut off the trailing newline of this given data
4118ca
 before comparing with the one actually received by the client
4118ca
 
4118ca
+`crlf=yes` forces the newlines to become CRLF even if not written so in the
4118ca
+test.
4118ca
+
4118ca
 ### `<file name="log/filename" [mode="text"]>`
4118ca
 The file's contents must be identical to this after the test is complete.  Use
4118ca
 the mode="text" attribute if the output is in text mode on platforms that have
4118ca
diff --git a/tests/data/test1 b/tests/data/test1
4118ca
index f39a08b..700bed8 100644
4118ca
--- a/tests/data/test1
4118ca
+++ b/tests/data/test1
4118ca
@@ -9,7 +9,7 @@ HTTP GET
4118ca
 #
4118ca
 # Server-side
4118ca
 <reply>
4118ca
-<data>
4118ca
+<data crlf="yes">
4118ca
 HTTP/1.1 200 OK
4118ca
 Date: Tue, 09 Nov 2010 14:49:00 GMT
4118ca
 Server: test-server/fake
4118ca
@@ -42,12 +42,12 @@ http://%HOSTIP:%HTTPPORT/%TESTNUMBER
4118ca
 #
4118ca
 # Verify data after the test has been "shot"
4118ca
 <verify>
4118ca
-<protocol>
4118ca
-GET /%TESTNUMBER HTTP/1.1
4118ca
-Host: %HOSTIP:%HTTPPORT
4118ca
-User-Agent: curl/%VERSION
4118ca
-Accept: */*
4118ca
-
4118ca
+<protocol crlf="yes">
4118ca
+GET /%TESTNUMBER HTTP/1.1
4118ca
+Host: %HOSTIP:%HTTPPORT
4118ca
+User-Agent: curl/%VERSION
4118ca
+Accept: */*
4118ca
+
4118ca
 </protocol>
4118ca
 </verify>
4118ca
 </testcase>
4118ca
diff --git a/tests/runtests.pl b/tests/runtests.pl
4118ca
index 72a9989..b12a42d 100755
4118ca
--- a/tests/runtests.pl
4118ca
+++ b/tests/runtests.pl
4118ca
@@ -3410,7 +3410,13 @@ sub subBase64 {
4118ca
 
4118ca
 my $prevupdate;
4118ca
 sub subNewlines {
4118ca
-    my ($thing) = @_;
4118ca
+    my ($force, $thing) = @_;
4118ca
+
4118ca
+    if($force) {
4118ca
+        # enforce CRLF newline
4118ca
+        $$thing =~ s/\x0d*\x0a/\x0d\x0a/;
4118ca
+        return;
4118ca
+    }
4118ca
 
4118ca
     # When curl is built with Hyper, it gets all response headers delivered as
4118ca
     # name/value pairs and curl "invents" the newlines when it saves the
4118ca
@@ -3424,7 +3430,7 @@ sub subNewlines {
4118ca
         # skip curl error messages
4118ca
         ($$thing !~ /^curl: \(\d+\) /))) {
4118ca
         # enforce CRLF newline
4118ca
-        $$thing =~ s/\x0a/\x0d\x0a/;
4118ca
+        $$thing =~ s/\x0d*\x0a/\x0d\x0a/;
4118ca
         $prevupdate = 1;
4118ca
     }
4118ca
     else {
4118ca
@@ -3496,6 +3502,7 @@ sub prepro {
4118ca
     my (@entiretest) = @_;
4118ca
     my $show = 1;
4118ca
     my @out;
4118ca
+    my $data_crlf;
4118ca
     for my $s (@entiretest) {
4118ca
         my $f = $s;
4118ca
         if($s =~ /^ *%if (.*)/) {
4118ca
@@ -3519,9 +3526,19 @@ sub prepro {
4118ca
             next;
4118ca
         }
4118ca
         if($show) {
4118ca
+            # The processor does CRLF replacements in the <data*> sections if
4118ca
+            # necessary since those parts might be read by separate servers.
4118ca
+            if($s =~ /^ *<data(.*)\>/) {
4118ca
+                if($1 =~ /crlf="yes"/ || $has_hyper) {
4118ca
+                    $data_crlf = 1;
4118ca
+                }
4118ca
+            }
4118ca
+            elsif(($s =~ /^ *<\/data/) && $data_crlf) {
4118ca
+                $data_crlf = 0;
4118ca
+            }
4118ca
             subVariables(\$s, $testnum, "%");
4118ca
             subBase64(\$s);
4118ca
-            subNewlines(\$s) if($has_hyper);
4118ca
+            subNewlines(0, \$s) if($data_crlf);
4118ca
             push @out, $s;
4118ca
         }
4118ca
     }
4118ca
@@ -3830,6 +3847,11 @@ sub singletest {
4118ca
                     # of the datacheck
4118ca
                     chomp($replycheckpart[$#replycheckpart]);
4118ca
                 }
4118ca
+                if($replycheckpartattr{'crlf'} ||
4118ca
+                   ($has_hyper && ($keywords{"HTTP"}
4118ca
+                                   || $keywords{"HTTPS"}))) {
4118ca
+                    map subNewlines(0, \$_), @replycheckpart;
4118ca
+                }
4118ca
                 push(@reply, @replycheckpart);
4118ca
             }
4118ca
         }
4118ca
@@ -3851,6 +3873,11 @@ sub singletest {
4118ca
             map s/\r\n/\n/g, @reply;
4118ca
             map s/\n/\r\n/g, @reply;
4118ca
         }
4118ca
+        if($replyattr{'crlf'} ||
4118ca
+           ($has_hyper && ($keywords{"HTTP"}
4118ca
+                           || $keywords{"HTTPS"}))) {
4118ca
+            map subNewlines(0, \$_), @reply;
4118ca
+        }
4118ca
     }
4118ca
 
4118ca
     # this is the valid protocol blurb curl should generate
4118ca
@@ -4287,6 +4314,12 @@ sub singletest {
4118ca
             chomp($validstdout[$#validstdout]);
4118ca
         }
4118ca
 
4118ca
+        if($hash{'crlf'} ||
4118ca
+           ($has_hyper && ($keywords{"HTTP"}
4118ca
+                           || $keywords{"HTTPS"}))) {
4118ca
+            map subNewlines(0, \$_), @validstdout;
4118ca
+        }
4118ca
+
4118ca
         $res = compare($testnum, $testname, "stdout", \@actual, \@validstdout);
4118ca
         if($res) {
4118ca
             return $errorreturncode;
4118ca
@@ -4381,6 +4414,10 @@ sub singletest {
4118ca
             }
4118ca
         }
4118ca
 
4118ca
+        if($hash{'crlf'}) {
4118ca
+            map subNewlines(1, \$_), @protstrip;
4118ca
+        }
4118ca
+
4118ca
         if((!$out[0] || ($out[0] eq "")) && $protstrip[0]) {
4118ca
             logmsg "\n $testnum: protocol FAILED!\n".
4118ca
                 " There was no content at all in the file $SERVERIN.\n".
4118ca
@@ -4512,6 +4549,11 @@ sub singletest {
4118ca
                 map s/\r\n/\n/g, @outfile;
4118ca
                 map s/\n/\r\n/g, @outfile;
4118ca
             }
4118ca
+            if($hash{'crlf'} ||
4118ca
+               ($has_hyper && ($keywords{"HTTP"}
4118ca
+                               || $keywords{"HTTPS"}))) {
4118ca
+                map subNewlines(0, \$_), @outfile;
4118ca
+            }
4118ca
 
4118ca
             my $strip;
4118ca
             for $strip (@stripfile) {
4118ca
-- 
4118ca
2.39.1
4118ca
4118ca
4118ca
From 228ed11bf33c63d9208a3fb38fe5a0d19c0764bd Mon Sep 17 00:00:00 2001
4118ca
From: Daniel Stenberg <daniel@haxx.se>
4118ca
Date: Tue, 27 Dec 2022 11:50:23 +0100
4118ca
Subject: [PATCH 3/4] runtests: support crlf="yes" for verify/proxy
4118ca
4118ca
Upstream-commit: dc0725244a3163f1e2d5f51165db3a1a430f3ba0
4118ca
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
4118ca
---
4118ca
 tests/FILEFORMAT.md | 4 ++--
4118ca
 tests/runtests.pl   | 5 +++++
4118ca
 2 files changed, 7 insertions(+), 2 deletions(-)
4118ca
4118ca
diff --git a/tests/FILEFORMAT.md b/tests/FILEFORMAT.md
4118ca
index dcb5695..6646793 100644
4118ca
--- a/tests/FILEFORMAT.md
4118ca
+++ b/tests/FILEFORMAT.md
4118ca
@@ -532,7 +532,7 @@ changing protocol data such as port numbers or user-agent strings.
4118ca
 One perl op per line that operates on the protocol dump. This is pretty
4118ca
 advanced. Example: `s/^EPRT .*/EPRT stripped/`.
4118ca
 
4118ca
-### `<protocol [nonewline="yes"] crlf="yes">`
4118ca
+### `<protocol [nonewline="yes"][crlf="yes"]>`
4118ca
 
4118ca
 the protocol dump curl should transmit, if 'nonewline' is set, we will cut off
4118ca
 the trailing newline of this given data before comparing with the one actually
4118ca
@@ -542,7 +542,7 @@ comparisons are made.
4118ca
 `crlf=yes` forces the newlines to become CRLF even if not written so in the
4118ca
 test.
4118ca
 
4118ca
-### `<proxy [nonewline="yes"]>`
4118ca
+### `<proxy [nonewline="yes"][crlf="yes"]>`
4118ca
 
4118ca
 The protocol dump curl should transmit to a HTTP proxy (when the http-proxy
4118ca
 server is used), if 'nonewline' is set, we will cut off the trailing newline
4118ca
diff --git a/tests/runtests.pl b/tests/runtests.pl
4118ca
index b12a42d..5cdc83d 100755
4118ca
--- a/tests/runtests.pl
4118ca
+++ b/tests/runtests.pl
4118ca
@@ -4510,6 +4510,11 @@ sub singletest {
4118ca
             }
4118ca
         }
4118ca
 
4118ca
+        if($hash{'crlf'} ||
4118ca
+           ($has_hyper && ($keywords{"HTTP"} || $keywords{"HTTPS"}))) {
4118ca
+            map subNewlines(0, \$_), @protstrip;
4118ca
+        }
4118ca
+
4118ca
         $res = compare($testnum, $testname, "proxy", \@out, \@protstrip);
4118ca
         if($res) {
4118ca
             return $errorreturncode;
4118ca
-- 
4118ca
2.39.1
4118ca
4118ca
4118ca
From bc5fc958b017895728962c9d44c469418cbec1a0 Mon Sep 17 00:00:00 2001
4118ca
From: Patrick Monnerat <patrick@monnerat.net>
4118ca
Date: Mon, 13 Feb 2023 08:33:09 +0100
4118ca
Subject: [PATCH 4/4] content_encoding: do not reset stage counter for each
4118ca
 header
4118ca
4118ca
Test 418 verifies
4118ca
4118ca
Closes #10492
4118ca
4118ca
Upstream-commit: 119fb187192a9ea13dc90d9d20c215fc82799ab9
4118ca
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
4118ca
---
4118ca
 lib/content_encoding.c  |   7 +-
4118ca
 lib/urldata.h           |   1 +
4118ca
 tests/data/Makefile.inc |   1 +
4118ca
 tests/data/test387      |   2 +-
4118ca
 tests/data/test418      | 152 ++++++++++++++++++++++++++++++++++++++++
4118ca
 5 files changed, 158 insertions(+), 5 deletions(-)
4118ca
 create mode 100644 tests/data/test418
4118ca
4118ca
diff --git a/lib/content_encoding.c b/lib/content_encoding.c
4118ca
index bfc13e2..94344d6 100644
4118ca
--- a/lib/content_encoding.c
4118ca
+++ b/lib/content_encoding.c
4118ca
@@ -1033,7 +1033,6 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
4118ca
                                      const char *enclist, int maybechunked)
4118ca
 {
4118ca
   struct SingleRequest *k = &data->req;
4118ca
-  int counter = 0;
4118ca
 
4118ca
   do {
4118ca
     const char *name;
4118ca
@@ -1068,9 +1067,9 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
4118ca
       if(!encoding)
4118ca
         encoding = &error_encoding;  /* Defer error at stack use. */
4118ca
 
4118ca
-      if(++counter >= MAX_ENCODE_STACK) {
4118ca
-        failf(data, "Reject response due to %u content encodings",
4118ca
-              counter);
4118ca
+      if(k->writer_stack_depth++ >= MAX_ENCODE_STACK) {
4118ca
+        failf(data, "Reject response due to more than %u content encodings",
4118ca
+              MAX_ENCODE_STACK);
4118ca
         return CURLE_BAD_CONTENT_ENCODING;
4118ca
       }
4118ca
       /* Stack the unencoding stage. */
4118ca
diff --git a/lib/urldata.h b/lib/urldata.h
4118ca
index 5b4b34f..8c8c20b 100644
4118ca
--- a/lib/urldata.h
4118ca
+++ b/lib/urldata.h
4118ca
@@ -700,6 +700,7 @@ struct SingleRequest {
4118ca
 #ifndef CURL_DISABLE_DOH
4118ca
   struct dohdata *doh; /* DoH specific data for this request */
4118ca
 #endif
4118ca
+  unsigned char writer_stack_depth; /* Unencoding stack depth. */
4118ca
   BIT(header);       /* incoming data has HTTP header */
4118ca
   BIT(content_range); /* set TRUE if Content-Range: was found */
4118ca
   BIT(upload_done);  /* set to TRUE when doing chunked transfer-encoding
4118ca
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
4118ca
index fb51cd6..86b6f85 100644
4118ca
--- a/tests/data/Makefile.inc
4118ca
+++ b/tests/data/Makefile.inc
4118ca
@@ -67,6 +67,7 @@ test393 test394 test395 test396 test397 \
4118ca
 \
4118ca
 test400 test401 test402 test403 test404 test405 test406 test407 test408 \
4118ca
 test409 test410 \
4118ca
+        test418 \
4118ca
 \
4118ca
 test430 test431 test432 test433 test434 \
4118ca
 \
4118ca
diff --git a/tests/data/test387 b/tests/data/test387
4118ca
index 015ec25..644fc7f 100644
4118ca
--- a/tests/data/test387
4118ca
+++ b/tests/data/test387
4118ca
@@ -47,7 +47,7 @@ Accept: */*
4118ca
 61
4118ca
 </errorcode>
4118ca
 <stderr mode="text">
4118ca
-curl: (61) Reject response due to 5 content encodings
4118ca
+curl: (61) Reject response due to more than 5 content encodings
4118ca
 </stderr>
4118ca
 </verify>
4118ca
 </testcase>
4118ca
diff --git a/tests/data/test418 b/tests/data/test418
4118ca
new file mode 100644
4118ca
index 0000000..50e974e
4118ca
--- /dev/null
4118ca
+++ b/tests/data/test418
4118ca
@@ -0,0 +1,152 @@
4118ca
+<testcase>
4118ca
+<info>
4118ca
+<keywords>
4118ca
+HTTP
4118ca
+gzip
4118ca
+</keywords>
4118ca
+</info>
4118ca
+
4118ca
+#
4118ca
+# Server-side
4118ca
+<reply>
4118ca
+<data nocheck="yes">
4118ca
+HTTP/1.1 200 OK
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+Transfer-Encoding: gzip
4118ca
+
4118ca
+-foo-
4118ca
+</data>
4118ca
+</reply>
4118ca
+
4118ca
+#
4118ca
+# Client-side
4118ca
+<client>
4118ca
+<server>
4118ca
+http
4118ca
+</server>
4118ca
+ <name>
4118ca
+Response with multiple Transfer-Encoding headers
4118ca
+ </name>
4118ca
+ <command>
4118ca
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -sS
4118ca
+</command>
4118ca
+</client>
4118ca
+
4118ca
+#
4118ca
+# Verify data after the test has been "shot"
4118ca
+<verify>
4118ca
+<protocol crlf="yes">
4118ca
+GET /%TESTNUMBER HTTP/1.1
4118ca
+Host: %HOSTIP:%HTTPPORT
4118ca
+User-Agent: curl/%VERSION
4118ca
+Accept: */*
4118ca
+
4118ca
+</protocol>
4118ca
+
4118ca
+# CURLE_BAD_CONTENT_ENCODING is 61
4118ca
+<errorcode>
4118ca
+61
4118ca
+</errorcode>
4118ca
+<stderr mode="text">
4118ca
+curl: (61) Reject response due to more than 5 content encodings
4118ca
+</stderr>
4118ca
+</verify>
4118ca
+</testcase>
4118ca
-- 
4118ca
2.39.1
4118ca