1From 119fb187192a9ea13dc90d9d20c215fc82799ab9 Mon Sep 17 00:00:00 2001 2From: Patrick Monnerat <patrick@monnerat.net> 3Date: Mon, 13 Feb 2023 08:33:09 +0100 4Subject: [PATCH] content_encoding: do not reset stage counter for each header 5 6Test 418 verifies 7 8Closes #10492 9 10CVE: CVE-2023-23916 11Upstream-Status: Backport [https://github.com/curl/curl/commit/119fb187192a9ea13dc.patch] 12Signed-off-by: Pawan Badganchi <Pawan.Badganchi@kpit.com> 13--- 14 lib/content_encoding.c | 7 +- 15 lib/urldata.h | 1 + 16 tests/data/Makefile.inc | 2 +- 17 tests/data/test387 | 2 +- 18 tests/data/test418 | 152 ++++++++++++++++++++++++++++++++++++++++ 19 5 files changed, 158 insertions(+), 6 deletions(-) 20 create mode 100644 tests/data/test418 21 22--- a/lib/content_encoding.c 23+++ b/lib/content_encoding.c 24@@ -1037,7 +1037,6 @@ CURLcode Curl_build_unencoding_stack(str 25 const char *enclist, int maybechunked) 26 { 27 struct SingleRequest *k = &data->req; 28- int counter = 0; 29 30 do { 31 const char *name; 32@@ -1072,9 +1071,9 @@ CURLcode Curl_build_unencoding_stack(str 33 if(!encoding) 34 encoding = &error_encoding; /* Defer error at stack use. */ 35 36- if(++counter >= MAX_ENCODE_STACK) { 37- failf(data, "Reject response due to %u content encodings", 38- counter); 39+ if(k->writer_stack_depth++ >= MAX_ENCODE_STACK) { 40+ failf(data, "Reject response due to more than %u content encodings", 41+ MAX_ENCODE_STACK); 42 return CURLE_BAD_CONTENT_ENCODING; 43 } 44 /* Stack the unencoding stage. */ 45--- a/lib/urldata.h 46+++ b/lib/urldata.h 47@@ -682,6 +682,7 @@ struct SingleRequest { 48 struct dohdata *doh; /* DoH specific data for this request */ 49 #endif 50 unsigned char setcookies; 51+ unsigned char writer_stack_depth; /* Unencoding stack depth. */ 52 BIT(header); /* incoming data has HTTP header */ 53 BIT(content_range); /* set TRUE if Content-Range: was found */ 54 BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding 55--- a/tests/data/Makefile.inc 56+++ b/tests/data/Makefile.inc 57@@ -69,6 +69,7 @@ 58 \ 59 test400 test401 test402 test403 test404 test405 test406 test407 test408 \ 60 test409 test410 \ 61+test418 \ 62 \ 63 test430 test431 test432 test433 test434 test435 test436 \ 64 \ 65--- /dev/null 66+++ b/tests/data/test418 67@@ -0,0 +1,152 @@ 68+<testcase> 69+<info> 70+<keywords> 71+HTTP 72+gzip 73+</keywords> 74+</info> 75+ 76+# 77+# Server-side 78+<reply> 79+<data nocheck="yes"> 80+HTTP/1.1 200 OK 81+Transfer-Encoding: gzip 82+Transfer-Encoding: gzip 83+Transfer-Encoding: gzip 84+Transfer-Encoding: gzip 85+Transfer-Encoding: gzip 86+Transfer-Encoding: gzip 87+Transfer-Encoding: gzip 88+Transfer-Encoding: gzip 89+Transfer-Encoding: gzip 90+Transfer-Encoding: gzip 91+Transfer-Encoding: gzip 92+Transfer-Encoding: gzip 93+Transfer-Encoding: gzip 94+Transfer-Encoding: gzip 95+Transfer-Encoding: gzip 96+Transfer-Encoding: gzip 97+Transfer-Encoding: gzip 98+Transfer-Encoding: gzip 99+Transfer-Encoding: gzip 100+Transfer-Encoding: gzip 101+Transfer-Encoding: gzip 102+Transfer-Encoding: gzip 103+Transfer-Encoding: gzip 104+Transfer-Encoding: gzip 105+Transfer-Encoding: gzip 106+Transfer-Encoding: gzip 107+Transfer-Encoding: gzip 108+Transfer-Encoding: gzip 109+Transfer-Encoding: gzip 110+Transfer-Encoding: gzip 111+Transfer-Encoding: gzip 112+Transfer-Encoding: gzip 113+Transfer-Encoding: gzip 114+Transfer-Encoding: gzip 115+Transfer-Encoding: gzip 116+Transfer-Encoding: gzip 117+Transfer-Encoding: gzip 118+Transfer-Encoding: gzip 119+Transfer-Encoding: gzip 120+Transfer-Encoding: gzip 121+Transfer-Encoding: gzip 122+Transfer-Encoding: gzip 123+Transfer-Encoding: gzip 124+Transfer-Encoding: gzip 125+Transfer-Encoding: gzip 126+Transfer-Encoding: gzip 127+Transfer-Encoding: gzip 128+Transfer-Encoding: gzip 129+Transfer-Encoding: gzip 130+Transfer-Encoding: gzip 131+Transfer-Encoding: gzip 132+Transfer-Encoding: gzip 133+Transfer-Encoding: gzip 134+Transfer-Encoding: gzip 135+Transfer-Encoding: gzip 136+Transfer-Encoding: gzip 137+Transfer-Encoding: gzip 138+Transfer-Encoding: gzip 139+Transfer-Encoding: gzip 140+Transfer-Encoding: gzip 141+Transfer-Encoding: gzip 142+Transfer-Encoding: gzip 143+Transfer-Encoding: gzip 144+Transfer-Encoding: gzip 145+Transfer-Encoding: gzip 146+Transfer-Encoding: gzip 147+Transfer-Encoding: gzip 148+Transfer-Encoding: gzip 149+Transfer-Encoding: gzip 150+Transfer-Encoding: gzip 151+Transfer-Encoding: gzip 152+Transfer-Encoding: gzip 153+Transfer-Encoding: gzip 154+Transfer-Encoding: gzip 155+Transfer-Encoding: gzip 156+Transfer-Encoding: gzip 157+Transfer-Encoding: gzip 158+Transfer-Encoding: gzip 159+Transfer-Encoding: gzip 160+Transfer-Encoding: gzip 161+Transfer-Encoding: gzip 162+Transfer-Encoding: gzip 163+Transfer-Encoding: gzip 164+Transfer-Encoding: gzip 165+Transfer-Encoding: gzip 166+Transfer-Encoding: gzip 167+Transfer-Encoding: gzip 168+Transfer-Encoding: gzip 169+Transfer-Encoding: gzip 170+Transfer-Encoding: gzip 171+Transfer-Encoding: gzip 172+Transfer-Encoding: gzip 173+Transfer-Encoding: gzip 174+Transfer-Encoding: gzip 175+Transfer-Encoding: gzip 176+Transfer-Encoding: gzip 177+Transfer-Encoding: gzip 178+Transfer-Encoding: gzip 179+Transfer-Encoding: gzip 180+Transfer-Encoding: gzip 181+ 182+-foo- 183+</data> 184+</reply> 185+ 186+# 187+# Client-side 188+<client> 189+<server> 190+http 191+</server> 192+ <name> 193+Response with multiple Transfer-Encoding headers 194+ </name> 195+ <command> 196+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -sS 197+</command> 198+</client> 199+ 200+# 201+# Verify data after the test has been "shot" 202+<verify> 203+<protocol crlf="yes"> 204+GET /%TESTNUMBER HTTP/1.1 205+Host: %HOSTIP:%HTTPPORT 206+User-Agent: curl/%VERSION 207+Accept: */* 208+ 209+</protocol> 210+ 211+# CURLE_BAD_CONTENT_ENCODING is 61 212+<errorcode> 213+61 214+</errorcode> 215+<stderr mode="text"> 216+curl: (61) Reject response due to more than 5 content encodings 217+</stderr> 218+</verify> 219+</testcase> 220