1- From 3dbb793d73f7aa0be3dde72a44877c16698dee5c Mon Sep 17 00:00:00 2001
2- From: AllSpark <allspark@microsoft .com>
3- Date: Tue, 17 Feb 2026 02:44:11 +0000
1+ From 30b682af333402eeef4fad3acbc865771f85281a Mon Sep 17 00:00:00 2001
2+ From: Carlos Garcia Campos <cgarcia@igalia .com>
3+ Date: Thu, 29 Jan 2026 16:43:28 +0100
44Subject: [PATCH] server: close the connection after responsing a request
55 containing Content-Length and Transfer-Encoding
66
77Closes #475
88
9- - Recompute encoding lazily prioritizing Transfer-Encoding over Content-Length.
10- - Ensure server closes connection when both headers are present by setting Connection: close.
11-
12- Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
13- Upstream-reference: AI Backport of https://gitlab.gnome.org/GNOME/libsoup/-/commit/30b682af333402eeef4fad3acbc865771f85281a.patch
9+ Upstream Patch Reference: https://gitlab.gnome.org/GNOME/libsoup/-/commit/30b682af333402eeef4fad3acbc865771f85281a.patch
1410---
15- libsoup/server/soup-server-io.c | 9 ++++
16- libsoup/soup-message-headers.c | 88 +++++++++++++++------------------
17- 2 files changed, 50 insertions(+), 47 deletions(-)
11+ libsoup/server/soup-server-io.c | 8 +++
12+ libsoup/soup-message-headers.c | 86 +++++++++++++++------------------
13+ tests/server-test.c | 4 +-
14+ 3 files changed, 51 insertions(+), 47 deletions(-)
1815
1916diff --git a/libsoup/server/soup-server-io.c b/libsoup/server/soup-server-io.c
20- index 7e9cc45..0efb9b7 100644
17+ index 7e9cc45..9e237a3 100644
2118--- a/libsoup/server/soup-server-io.c
2219+++ b/libsoup/server/soup-server-io.c
23- @@ -599,6 +599,15 @@ parse_headers (SoupServerMessage *msg,
20+ @@ -599,6 +599,14 @@ parse_headers (SoupServerMessage *msg,
2421 return SOUP_STATUS_BAD_REQUEST;
2522 }
2623
@@ -31,13 +28,12 @@ index 7e9cc45..0efb9b7 100644
3128+ */
3229+ if (*encoding == SOUP_ENCODING_CHUNKED && soup_message_headers_get_one_common (request_headers, SOUP_HEADER_CONTENT_LENGTH))
3330+ soup_message_headers_replace_common (request_headers, SOUP_HEADER_CONNECTION, "close", TRUE);
34- +
3531+
3632 /* Generate correct context for request */
3733 req_host = soup_message_headers_get_one_common (request_headers, SOUP_HEADER_HOST);
3834 if (req_host && strchr (req_host, '/')) {
3935diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c
40- index d71a2cf..1a6be25 100644
36+ index d71a2cf..c668899 100644
4137--- a/libsoup/soup-message-headers.c
4238+++ b/libsoup/soup-message-headers.c
4339@@ -155,19 +155,8 @@ soup_message_headers_set (SoupMessageHeaders *hdrs,
@@ -62,7 +58,7 @@ index d71a2cf..1a6be25 100644
6258 break;
6359 case SOUP_HEADER_CONTENT_TYPE:
6460 g_clear_pointer (&hdrs->content_type, g_free);
65- @@ -193,21 +182,7 @@ soup_message_headers_set (SoupMessageHeaders *hdrs,
61+ @@ -193,21 +182,6 @@ soup_message_headers_set (SoupMessageHeaders *hdrs,
6662 } else
6763 hdrs->expectations = 0;
6864 break;
@@ -81,11 +77,10 @@ index d71a2cf..1a6be25 100644
8177- } else
8278- hdrs->encoding = -1;
8379- break;
84- + /* SOUP_HEADER_TRANSFER_ENCODING handled by recomputing encoding lazily */
8580 default:
8681 break;
8782 }
88- @@ -951,30 +926,49 @@ soup_message_headers_foreach (SoupMessageHeaders *hdrs,
83+ @@ -951,30 +925,50 @@ soup_message_headers_foreach (SoupMessageHeaders *hdrs,
8984 SoupEncoding
9085 soup_message_headers_get_encoding (SoupMessageHeaders *hdrs)
9186 {
@@ -104,24 +99,43 @@ index d71a2cf..1a6be25 100644
10499- soup_message_headers_set (hdrs, SOUP_HEADER_CONTENT_LENGTH, header);
105100- if (hdrs->encoding != -1)
106101- return hdrs->encoding;
107- - }
108- + /* Transfer-Encoding is checked first because it overrides the Content-Length */
102+ + /* Transfer-Encoding is checked first because it overrides the Content-Length */
109103+ transfer_encoding = soup_message_headers_get_one_common (hdrs, SOUP_HEADER_TRANSFER_ENCODING);
110104+ if (transfer_encoding) {
111105+ /* "identity" is a wrong value according to RFC errata 408,
112106+ * and RFC 7230 does not list it as valid transfer-coding.
113107+ * Nevertheless, the obsolete RFC 2616 stated "identity"
114108+ * as valid, so we can't handle it as unrecognized here
115109+ * for compatibility reasons.
116- + */
117- + if (g_ascii_strcasecmp (transfer_encoding, "chunked") == 0)
110+ + */
111+ + if (g_ascii_strcasecmp (transfer_encoding, "chunked") == 0)
118112+ hdrs->encoding = SOUP_ENCODING_CHUNKED;
119113+ else if (g_ascii_strcasecmp (transfer_encoding, "identity") != 0)
120114+ hdrs->encoding = SOUP_ENCODING_UNRECOGNIZED;
121115+ } else {
122116+ content_length = soup_message_headers_get_one_common (hdrs, SOUP_HEADER_CONTENT_LENGTH);
123117+ if (content_length) {
124118+ char *end;
119+ +
120+ + hdrs->content_length = g_ascii_strtoull (content_length, &end, 10);
121+ + if (*end)
122+ + hdrs->encoding = SOUP_ENCODING_UNRECOGNIZED;
123+ + else
124+ + hdrs->encoding = SOUP_ENCODING_CONTENT_LENGTH;
125+ + }
126+ + }
127+ +
128+ + if (hdrs->encoding == -1) {
129+ + /* Per RFC 2616 4.4, a response body that doesn't indicate its
130+ + * encoding otherwise is terminated by connection close, and a
131+ + * request that doesn't indicate otherwise has no body. Note
132+ + * that SoupMessage calls soup_message_headers_set_encoding()
133+ + * to override the response body default for our own
134+ + * server-side messages.
135+ + */
136+ + hdrs->encoding = (hdrs->type == SOUP_MESSAGE_HEADERS_RESPONSE) ?
137+ + SOUP_ENCODING_EOF : SOUP_ENCODING_NONE;
138+ }
125139
126140- /* Per RFC 2616 4.4, a response body that doesn't indicate its
127141- * encoding otherwise is terminated by connection close, and a
@@ -132,28 +146,24 @@ index d71a2cf..1a6be25 100644
132146- */
133147- hdrs->encoding = (hdrs->type == SOUP_MESSAGE_HEADERS_RESPONSE) ?
134148- SOUP_ENCODING_EOF : SOUP_ENCODING_NONE;
135- + hdrs->content_length = g_ascii_strtoull (content_length, &end, 10);
136- + if (*end)
137- + hdrs->encoding = SOUP_ENCODING_UNRECOGNIZED;
138- + else
139- + hdrs->encoding = SOUP_ENCODING_CONTENT_LENGTH;
140- + }
141- + }
142- +
143- + if (hdrs->encoding == -1) {
144- + /* Per RFC 2616 4.4, a response body that doesn't indicate its
145- + * encoding otherwise is terminated by connection close, and a
146- + * request that doesn't indicate otherwise has no body. Note
147- + * that SoupMessage calls soup_message_headers_set_encoding()
148- + * to override the response body default for our own
149- + * server-side messages.
150- + */
151- + hdrs->encoding = (hdrs->type == SOUP_MESSAGE_HEADERS_RESPONSE) ?
152- + SOUP_ENCODING_EOF : SOUP_ENCODING_NONE;
153- + }
154149 return hdrs->encoding;
155150 }
156151
152+ diff --git a/tests/server-test.c b/tests/server-test.c
153+ index b8f09d3..292dcef 100644
154+ --- a/tests/server-test.c
155+ +++ b/tests/server-test.c
156+ @@ -1317,7 +1317,9 @@ do_chunked_test (ServerData *sd, gconstpointer test_data)
157+ const char *description;
158+ const char *test;
159+ } tests[] = {
160+ - { "Lone LF", "Transfer-Encoding: chunked\r\n\r\n5;ext\n data\r\n0\r\n\r\n" },
161+ + { "Single LF", "Transfer-Encoding: chunked\r\n\r\n5;ext\n data\r\n0\r\n\r\n" },
162+ + { "Content-Length and Transfer-Encoding", "Content-Length: 4\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\n" },
163+ + { "Content-Length and Transfer-Encoding with keep alive connection", "Content-Length: 4\r\nTransfer-Encoding: chunked\r\nConnection: keep-alive\r\n\r\n0\r\n\r\n" },
164+ };
165+
166+ sd->server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
157167- -
1581682.45.4
159169
0 commit comments