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

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