File libsoup-CVE-2026-1760.patch of Package libsoup.42965
From 6224df5a471e9040a99dd3dc2e91817a701b1bf6 Mon Sep 17 00:00:00 2001
From: Carlos Garcia Campos <cgarcia@igalia.com>
Date: Thu, 29 Jan 2026 16:43:28 +0100
Subject: [PATCH] server: close the connection after responsing a request
containing Content-Length and Transfer-Encoding
Closes #475
---
.../http1/soup-server-message-io-http1.c | 8 ++
libsoup/soup-message-headers.c | 88 +++++++++----------
tests/server-test.c | 4 +-
3 files changed, 52 insertions(+), 48 deletions(-)
Index: libsoup-3.4.4/libsoup/server/http1/soup-server-message-io-http1.c
===================================================================
--- libsoup-3.4.4.orig/libsoup/server/http1/soup-server-message-io-http1.c
+++ libsoup-3.4.4/libsoup/server/http1/soup-server-message-io-http1.c
@@ -653,6 +653,14 @@ parse_headers (SoupServerMessage *msg,
return SOUP_STATUS_BAD_REQUEST;
}
+ /* A server MAY reject a request that contains both Content-Length and
+ * Transfer-Encoding or process such a request in accordance with the
+ * Transfer-Encoding alone. Regardless, the server MUST close the connection
+ * after responding to such a request to avoid the potential attacks
+ */
+ if (*encoding == SOUP_ENCODING_CHUNKED && soup_message_headers_get_one_common (request_headers, SOUP_HEADER_CONTENT_LENGTH))
+ soup_message_headers_replace_common (request_headers, SOUP_HEADER_CONNECTION, "close", 1);
+
/* Generate correct context for request */
req_host = soup_message_headers_get_one_common (request_headers, SOUP_HEADER_HOST);
if (req_host && strchr (req_host, '/')) {
Index: libsoup-3.4.4/libsoup/soup-message-headers.c
===================================================================
--- libsoup-3.4.4.orig/libsoup/soup-message-headers.c
+++ libsoup-3.4.4/libsoup/soup-message-headers.c
@@ -148,18 +148,6 @@ soup_message_headers_set (SoupMessageHea
{
switch (name) {
case SOUP_HEADER_CONTENT_LENGTH:
- if (hdrs->encoding == SOUP_ENCODING_CHUNKED)
- return;
-
- if (value) {
- char *end;
-
- hdrs->content_length = g_ascii_strtoull (value, &end, 10);
- if (*end)
- hdrs->encoding = SOUP_ENCODING_UNRECOGNIZED;
- else
- hdrs->encoding = SOUP_ENCODING_CONTENT_LENGTH;
- } else
hdrs->encoding = -1;
break;
case SOUP_HEADER_CONTENT_TYPE:
@@ -186,21 +174,6 @@ soup_message_headers_set (SoupMessageHea
} else
hdrs->expectations = 0;
break;
- case SOUP_HEADER_TRANSFER_ENCODING:
- if (value) {
- /* "identity" is a wrong value according to RFC errata 408,
- * and RFC 7230 does not list it as valid transfer-coding.
- * Nevertheless, the obsolete RFC 2616 stated "identity"
- * as valid, so we can't handle it as unrecognized here
- * for compatibility reasons.
- */
- if (g_ascii_strcasecmp (value, "chunked") == 0)
- hdrs->encoding = SOUP_ENCODING_CHUNKED;
- else if (g_ascii_strcasecmp (value, "identity") != 0)
- hdrs->encoding = SOUP_ENCODING_UNRECOGNIZED;
- } else
- hdrs->encoding = -1;
- break;
default:
break;
}
@@ -947,21 +920,39 @@ soup_message_headers_foreach (SoupMessag
SoupEncoding
soup_message_headers_get_encoding (SoupMessageHeaders *hdrs)
{
- const char *header;
+ const char *content_length;
+ const char *transfer_encoding;
if (hdrs->encoding != -1)
return hdrs->encoding;
- /* If Transfer-Encoding was set, hdrs->encoding would already
- * be set. So we don't need to check that possibility.
- */
- header = soup_message_headers_get_one_common (hdrs, SOUP_HEADER_CONTENT_LENGTH);
- if (header) {
- soup_message_headers_set (hdrs, SOUP_HEADER_CONTENT_LENGTH, header);
- if (hdrs->encoding != -1)
- return hdrs->encoding;
+ /* Transfer-Encoding is check first because it overrides the Content-Length */
+ transfer_encoding = soup_message_headers_get_one_common (hdrs, SOUP_HEADER_TRANSFER_ENCODING);
+ if (transfer_encoding) {
+ /* "identity" is a wrong value according to RFC errata 408,
+ * and RFC 7230 does not list it as valid transfer-coding.
+ * Nevertheless, the obsolete RFC 2616 stated "identity"
+ * as valid, so we can't handle it as unrecognized here
+ * for compatibility reasons.
+ */
+ if (g_ascii_strcasecmp (transfer_encoding, "chunked") == 0)
+ hdrs->encoding = SOUP_ENCODING_CHUNKED;
+ else if (g_ascii_strcasecmp (transfer_encoding, "identity") != 0)
+ hdrs->encoding = SOUP_ENCODING_UNRECOGNIZED;
+ } else {
+ content_length = soup_message_headers_get_one_common (hdrs, SOUP_HEADER_CONTENT_LENGTH);
+ if (content_length) {
+ char *end;
+
+ hdrs->content_length = g_ascii_strtoull (content_length, &end, 10);
+ if (*end)
+ hdrs->encoding = SOUP_ENCODING_UNRECOGNIZED;
+ else
+ hdrs->encoding = SOUP_ENCODING_CONTENT_LENGTH;
+ }
}
+ if (hdrs->encoding == -1) {
/* Per RFC 2616 4.4, a response body that doesn't indicate its
* encoding otherwise is terminated by connection close, and a
* request that doesn't indicate otherwise has no body. Note
@@ -971,6 +962,8 @@ soup_message_headers_get_encoding (SoupM
*/
hdrs->encoding = (hdrs->type == SOUP_MESSAGE_HEADERS_RESPONSE) ?
SOUP_ENCODING_EOF : SOUP_ENCODING_NONE;
+ }
+
return hdrs->encoding;
}