Package: curl Severity: normal Tags: patch User: ubuntu-de...@lists.ubuntu.com Usertags: origin-ubuntu kinetic ubuntu-patch
Dear Maintainer, In version 7.83.1, the support for multi-line headers is broken. This causes autopkgtest regressions in python-tornado: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1012224 In Ubuntu, the attached patch was applied to achieve the following: * Apply upstream patch to fix multi-line header support (LP: #1976619) Thanks for considering the patch. -- System Information: Debian Release: bookworm/sid APT prefers jammy-updates APT policy: (500, 'jammy-updates'), (500, 'jammy-security'), (500, 'jammy'), (100, 'jammy-backports') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 5.15.0-33-generic (SMP w/4 CPU threads) Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE not set Shell: /bin/sh linked to /usr/bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled
diff -Nru curl-7.83.1/debian/patches/12-http-restore-header-folding-behavior.patch curl-7.83.1/debian/patches/12-http-restore-header-folding-behavior.patch --- curl-7.83.1/debian/patches/12-http-restore-header-folding-behavior.patch 1970-01-01 01:00:00.000000000 +0100 +++ curl-7.83.1/debian/patches/12-http-restore-header-folding-behavior.patch 2022-06-02 13:44:50.000000000 +0200 @@ -0,0 +1,268 @@ +Description: restore header folding behavior + Folded header lines will now get passed through like before. The headers + API is adapted and will get and provide the content "un-folded". + Added test 1274 and extended test 1940 to verify. +Origin: upstream, https://github.com/curl/curl/pull/8899 +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/curl/+bug/1976619 +Applied-Upstream: https://github.com/curl/curl/commit/c9b60f005358a364cbcddbebd8d12593acffdd84 +Last-Update: 2022-06-02 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ +Index: b/docs/libcurl/curl_easy_header.3 +=================================================================== +--- a/docs/libcurl/curl_easy_header.3 2022-06-02 13:39:23.698800691 +0200 ++++ b/docs/libcurl/curl_easy_header.3 2022-06-02 13:39:23.694800445 +0200 +@@ -95,7 +95,9 @@ + + The data \fBvalue\fP field points to, comes exactly as delivered over the + network but with leading and trailing whitespace and newlines stripped +-off. The `value` data is nul-terminated. ++off. The `value` data is nul-terminated. For legacy HTTP/1 "folded headers", ++this API provides the full single value in an unfolded manner with a single ++whitespace between the lines. + + \fBamount\fP is how many headers using this name that exist, within the origin + and request scope asked for. +Index: b/lib/headers.c +=================================================================== +--- a/lib/headers.c 2022-06-02 13:39:23.698800691 +0200 ++++ b/lib/headers.c 2022-06-02 13:39:23.694800445 +0200 +@@ -216,6 +216,54 @@ + return CURLE_OK; + } + ++static CURLcode append_value(struct Curl_easy *data, const char *value, ++ size_t vlen) /* length of the incoming header */ ++{ ++ struct Curl_header_store *hs; ++ struct Curl_header_store *newhs; ++ size_t olen; /* length of the old value */ ++ size_t offset; ++ DEBUGASSERT(data->state.prevhead); ++ hs = data->state.prevhead; ++ olen = strlen(hs->value); ++ offset = hs->value - hs->buffer; ++ ++ /* skip all trailing space letters */ ++ while(vlen && ISSPACE(value[vlen - 1])) ++ vlen--; ++ ++ /* save only one leading space */ ++ while((vlen > 1) && ISSPACE(value[0]) && ISSPACE(value[1])) { ++ vlen--; ++ value++; ++ } ++ ++ /* since this header block might move in the realloc below, it needs to ++ first be unlinked from the list and then re-added again after the ++ realloc */ ++ Curl_llist_remove(&data->state.httphdrs, &hs->node, NULL); ++ ++ newhs = Curl_saferealloc(hs, sizeof(*hs) + vlen + olen + 1); ++ if(!newhs) ++ return CURLE_OUT_OF_MEMORY; ++ /* ->name' and ->value point into ->buffer (to keep the header allocation ++ in a single memory block), which now potentially have moved. Adjust ++ them. */ ++ newhs->name = newhs->buffer; ++ newhs->value = &newhs->buffer[offset]; ++ ++ /* put the data at the end of the previous data, not the newline */ ++ memcpy(&newhs->value[olen], value, vlen); ++ newhs->value[olen + vlen] = 0; /* zero terminate at newline */ ++ ++ /* insert this node into the list of headers */ ++ Curl_llist_insert_next(&data->state.httphdrs, data->state.httphdrs.tail, ++ newhs, &newhs->node); ++ data->state.prevhead = newhs; ++ return CURLE_OK; ++} ++ ++ + /* + * Curl_headers_push() gets passed a full HTTP header to store. It gets called + * immediately before the header callback. The header is CRLF terminated. +@@ -242,6 +290,10 @@ + } + hlen = end - header + 1; + ++ if((header[0] == ' ') || (header[0] == '\t')) ++ /* line folding, append value to the previous header's value */ ++ return append_value(data, header, hlen); ++ + hs = calloc(1, sizeof(*hs) + hlen); + if(!hs) + return CURLE_OUT_OF_MEMORY; +@@ -260,7 +312,7 @@ + /* insert this node into the list of headers */ + Curl_llist_insert_next(&data->state.httphdrs, data->state.httphdrs.tail, + hs, &hs->node); +- ++ data->state.prevhead = hs; + return CURLE_OK; + fail: + free(hs); +Index: b/lib/http.c +=================================================================== +--- a/lib/http.c 2022-06-02 13:39:23.698800691 +0200 ++++ b/lib/http.c 2022-06-02 13:39:23.698800691 +0200 +@@ -3799,11 +3799,16 @@ + if(k->headerline < 2) + /* the first "header" is the status-line and it has no colon */ + return CURLE_OK; +- ptr = memchr(header, ':', hlen); +- if(!ptr) { +- /* this is bad, bail out */ +- failf(data, "Header without colon"); +- return CURLE_WEIRD_SERVER_REPLY; ++ if(((header[0] == ' ') || (header[0] == '\t')) && k->headerline > 2) ++ /* line folding, can't happen on line 2 */ ++ ; ++ else { ++ ptr = memchr(header, ':', hlen); ++ if(!ptr) { ++ /* this is bad, bail out */ ++ failf(data, "Header without colon"); ++ return CURLE_WEIRD_SERVER_REPLY; ++ } + } + return CURLE_OK; + } +Index: b/lib/urldata.h +=================================================================== +--- a/lib/urldata.h 2022-06-02 13:39:23.698800691 +0200 ++++ b/lib/urldata.h 2022-06-02 13:39:23.698800691 +0200 +@@ -1425,6 +1425,7 @@ + headers */ + struct Curl_llist httphdrs; /* received headers */ + struct curl_header headerout; /* for external purposes */ ++ struct Curl_header_store *prevhead; /* the latest added header */ + #endif + trailers_state trailers_state; /* whether we are sending trailers + and what stage are we at */ +Index: b/tests/data/Makefile.inc +=================================================================== +--- a/tests/data/Makefile.inc 2022-06-02 13:39:23.698800691 +0200 ++++ b/tests/data/Makefile.inc 2022-06-02 13:39:23.698800691 +0200 +@@ -160,7 +160,7 @@ + test1248 test1249 test1250 test1251 test1252 test1253 test1254 test1255 \ + test1256 test1257 test1258 test1259 test1260 test1261 test1262 test1263 \ + test1264 test1265 test1266 test1267 test1268 test1269 test1270 test1271 \ +-test1272 test1273 \ ++test1272 test1273 test1274 \ + \ + test1280 test1281 test1282 test1283 test1284 test1285 test1286 test1287 \ + test1288 test1289 test1290 test1291 test1292 test1293 test1294 test1295 \ +Index: b/tests/data/test1274 +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ b/tests/data/test1274 2022-06-02 13:39:23.698800691 +0200 +@@ -0,0 +1,65 @@ ++<testcase> ++<info> ++<keywords> ++HTTP ++HTTP GET ++header line folding ++</keywords> ++</info> ++ ++# ++# Server-side ++<reply> ++<data> ++HTTP/1.1 200 OK ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/ ++ fake ++ folded ++Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT ++ETag: "21025-dc7-39462498" ++Content-Length: 6 ++Connection: close ++ ++-foo- ++</data> ++</reply> ++ ++# ++# Client-side ++<client> ++<server> ++http ++</server> ++ <name> ++HTTP header line folding ++ </name> ++ <command> ++http://%HOSTIP:%HTTPPORT/%TESTNUMBER -D log/out%TESTNUMBER ++</command> ++</client> ++ ++# ++# Verify data after the test has been "shot" ++<verify> ++<protocol> ++GET /%TESTNUMBER HTTP/1.1 ++Host: %HOSTIP:%HTTPPORT ++User-Agent: curl/%VERSION ++Accept: */* ++ ++</protocol> ++<file name="log/out%TESTNUMBER"> ++HTTP/1.1 200 OK ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/ ++ fake ++ folded ++Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT ++ETag: "21025-dc7-39462498" ++Content-Length: 6 ++Connection: close ++ ++</file> ++</verify> ++</testcase> +Index: b/tests/data/test1940 +=================================================================== +--- a/tests/data/test1940 2022-06-02 13:39:23.698800691 +0200 ++++ b/tests/data/test1940 2022-06-02 13:39:23.698800691 +0200 +@@ -12,6 +12,9 @@ + Date: Thu, 09 Nov 2010 14:49:00 GMT + Server: test with trailing space + Content-Type: text/html ++Fold: is ++ folding a ++ line + Content-Length: 0 + Set-Cookie: onecookie=data; + Set-Cookie: secondcookie=2data; +@@ -44,7 +47,7 @@ + + # Verify data after the test has been "shot" + <verify> +-<stdout> ++<stdout mode="text"> + Date == Thu, 09 Nov 2010 14:49:00 GMT + Server == test with trailing space + Content-Type == text/html +@@ -53,6 +56,7 @@ + - Set-Cookie == onecookie=data; (0/3) + - Set-Cookie == secondcookie=2data; (1/3) + - Set-Cookie == cookie3=data3; (2/3) ++ Fold == is folding a line + </stdout> + </verify> + </testcase> +Index: b/tests/libtest/lib1940.c +=================================================================== +--- a/tests/libtest/lib1940.c 2022-06-02 13:39:23.698800691 +0200 ++++ b/tests/libtest/lib1940.c 2022-06-02 13:39:23.698800691 +0200 +@@ -32,6 +32,7 @@ + "location", + "set-cookie", + "silly-thing", ++ "fold", + NULL + }; + diff -Nru curl-7.83.1/debian/patches/series curl-7.83.1/debian/patches/series --- curl-7.83.1/debian/patches/series 2022-05-11 18:46:48.000000000 +0200 +++ curl-7.83.1/debian/patches/series 2022-06-02 13:44:50.000000000 +0200 @@ -2,6 +2,7 @@ 06_always-disable-valgrind.patch 08_enable-zsh.patch 11_omit-directories-from-config.patch +12-http-restore-header-folding-behavior.patch # do not add patches below 90_gnutls.patch