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

Reply via email to