1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
From 0fca37e0fce479284e62091ffb9b7d6caff1c7e4 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
Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libsoup/-/commit/6224df5a471e9040a99dd3dc2e91817a701b1bf6]
CVE: CVE-2026-1760
Signed-off-by: Changqing Li <changqing.li@windriver.com>
---
libsoup/soup-message-headers.c | 86 +++++++++++++++-----------------
libsoup/soup-message-server-io.c | 8 +++
2 files changed, 49 insertions(+), 45 deletions(-)
diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c
index 535cf14..06d9600 100644
--- a/libsoup/soup-message-headers.c
+++ b/libsoup/soup-message-headers.c
@@ -666,38 +666,13 @@ clear_special_headers (SoupMessageHeaders *hdrs)
static void
transfer_encoding_setter (SoupMessageHeaders *hdrs, const char *value)
{
- 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;
+ hdrs->encoding = -1;
}
static void
content_length_setter (SoupMessageHeaders *hdrs, const char *value)
{
- /* Transfer-Encoding trumps 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;
+ hdrs->encoding = -1;
}
/**
@@ -730,29 +705,50 @@ 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 (hdrs, "Content-Length");
- if (header) {
- content_length_setter (hdrs, header);
- if (hdrs->encoding != -1)
- return hdrs->encoding;
- }
+ /* Transfer-Encoding is checked first because it overrides the Content-Length */
+ transfer_encoding = soup_message_headers_get_one (hdrs, "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 (hdrs, "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
+ * that SoupMessage calls soup_message_headers_set_encoding()
+ * to override the response body default for our own
+ * server-side messages.
+ */
+ hdrs->encoding = (hdrs->type == SOUP_MESSAGE_HEADERS_RESPONSE) ?
+ SOUP_ENCODING_EOF : SOUP_ENCODING_NONE;
+ }
- /* 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
- * that SoupMessage calls soup_message_headers_set_encoding()
- * to override the response body default for our own
- * server-side messages.
- */
- hdrs->encoding = (hdrs->type == SOUP_MESSAGE_HEADERS_RESPONSE) ?
- SOUP_ENCODING_EOF : SOUP_ENCODING_NONE;
return hdrs->encoding;
}
diff --git a/libsoup/soup-message-server-io.c b/libsoup/soup-message-server-io.c
index 71e943b..df5eafc 100644
--- a/libsoup/soup-message-server-io.c
+++ b/libsoup/soup-message-server-io.c
@@ -80,6 +80,14 @@ parse_request_headers (SoupMessage *msg, char *headers, guint headers_len,
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 (msg->request_headers, "Content-Length"))
+ soup_message_headers_replace (msg->request_headers, "Connection", "close");
+
/* Generate correct context for request */
req_host = soup_message_headers_get_one (msg->request_headers, "Host");
if (req_host && strchr (req_host, '/')) {
--
2.34.1
|