issue处理注意事项:
1. 提交正常修复分支的修复PR时,必须关联当前issue,否则无法关闭当前issue;
2. 模板内容需要填写完整, 无论是受影响或者不受影响都需要填写完整内容;
3. 以下为模板中需要填写完整的内容, 请复制到评论区回复;
注: 内容的关键词(影响性分析说明, openEuler评分, 受影响版本排查(受影响/不受影响), 修复是否涉及abi变化(是/否), 原因说明)不能省略,省略后cve-manager将无法正常解析填写内容.
影响性分析说明:
openEuler评分: (评分和向量)
受影响版本排查(受影响/不受影响):
1.master(3.7.2):
2.openEuler-20.03-LTS-SP4:
3.openEuler-22.03-LTS-SP4:
4.openEuler-24.03-LTS-Next(3.4.5):
5.openEuler-24.03-LTS-SP1(3.4.5):
6.openEuler-24.03-LTS-SP3(3.4.5):
7.openEuler-24.03-LTS-SP4(3.4.5):
修复是否涉及abi变化(是/否):
1.master(3.7.2):
2.openEuler-20.03-LTS-SP4:
3.openEuler-22.03-LTS-SP4:
4.openEuler-24.03-LTS-Next(3.4.5):
5.openEuler-24.03-LTS-SP1(3.4.5):
6.openEuler-24.03-LTS-SP3(3.4.5):
7.openEuler-24.03-LTS-SP4(3.4.5):
原因说明:
1.master(3.7.2):
2.openEuler-20.03-LTS-SP4:
3.openEuler-22.03-LTS-SP4:
4.openEuler-24.03-LTS-Next(3.4.5):
5.openEuler-24.03-LTS-SP1(3.4.5):
6.openEuler-24.03-LTS-SP3(3.4.5):
7.openEuler-24.03-LTS-SP4(3.4.5):
原因说明填写请参考下方表格(注意:版本是否受影响和版本的原因说明必须对应,例如master版本分支受影响,那原因说明只能是受影响对应的原因之一!):
分支状态 |
原因说明 | 使用场景 |
|---|---|---|
| 受影响 | 正常修复 | 受影响且需要修复(包含升级版本修复)的漏洞; 受影响且已经修复的漏洞(历史修复PR也需要关联issue); 若因特殊原因无法修复,应修改原因说明为【不修复-特殊原因】,并在安委会备案相关情况。 |
| 受影响 | 漏洞仍在分析中 | 已关注到相关漏洞,正在处理,未明确漏洞影响和修复方案。 |
| 受影响 | 暂不修复-暂无解决方案或补丁 | 当前没有可用的修复或补救措施。【影响性分析】中应包含有关为什么没有修复或补救措施的详细说明、上游相关PR等。 |
| 受影响 | 不修复-超出修复范围 | 没有漏洞的修复计划。当版本停维、软件包宣布生命周期终止或弃用使用。 |
| 受影响 | 不修复-特殊原因导致不再修复 | 如存在其他特殊情况不修复相关漏洞,或评估后无法升级修复,应在openEuler社区安全委员会例会进行说明备案。 【影响性分析】中应包含不发布修复的详细说明、特殊情况还应有安委会会议纪要。 |
| 不受影响 | 不受影响-组件不存在 | 软件不受影响,因为易受攻击的组件不在产品中。 |
| 不受影响 | 不受影响-已有内置的内联控制或缓解措施 | 内置的内联控制或缓解措施可防止攻击者利用漏洞 |
| 不受影响 | 不受影响-漏洞代码不能被攻击者触发 | 易受攻击的组件存在,并且该组件包含易受攻击的代码。但是,易受攻击的代码的使用方式使得攻击者无法进行任何预期的攻击。 |
| 不受影响 | 不受影响-漏洞代码不在执行路径 | 易受影响的代码在执行过程中不可访问,包括产品的非预期状态。产品不使用也不执行的组件。 |
| 不受影响 | 不受影响-漏洞代码不存在 | 产品不受影响,因为漏洞背后的代码在产品中不存在。与component_not_present不同的是,有问题的组件存在,但由于某种原因(例如安全的编译器选项)使漏洞的特定代码不存在于组件中。 |
issue处理具体操作请参考:
https://atomgit.com/openeuler/cve-manager/blob/master/cve-vulner-manager/doc/md/manual.md
pr关联issue具体操作请参考:
https://docs.atomgit.com/docs/help/home/org_project/pullrequests/pr-related-issue


Welcome To openEuler Community
Hey @openeuler-ci-bot , thanks for your contribution to the community.
Bot Usage Manual
I'm the Bot here serving you. You can find the instructions on how to interact with me at Here . That means you can comment below every pull request or issue to trigger Bot Commands.
Contact Guide
If you have any questions, please contact the SIG: GNOME ,
and any of the maintainers: @dwl301, @lw520203, @openbot, @robert-xingwang, @t_feng, @yanan-rock, @zhang__3125 ,
and any of the committers: @lvgenggeng, @technology208 .


| 参考网址 | 关联pr | 状态 | 补丁链接 |
|---|---|---|---|
| https://www.opencve.io/cve/CVE-2026-77014 | https://gitlab.gnome.org/GNOME/libsoup/-/merge_requests/550 | None | |
| https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2026-77014 | |||
| https://security-tracker.debian.org/tracker/CVE-2026-77014 | None | None | https://gitlab.gnome.org/GNOME/libsoup/-/commit/546a59d218eadc2f1006d4d9ecf0042666b88113 https://gitlab.gnome.org/GNOME/libsoup/-/commit/e82c13ba03defcee10f981ac964f4d570b21a251 https://gitlab.gnome.org/GNOME/libsoup/-/commit/6ece9e52d918cefa1e99b5f359a22b111bdced75 |
| http://www.cnnvd.org.cn/web/vulnerability/queryLds.tag?qcvCnnvdid=CVE-2026-77014 | |||
| https://nvd.nist.gov/vuln/detail/CVE-2026-77014 | https://gitlab.gnome.org/GNOME/libsoup/-/merge_requests/550 | None | |
| https://ubuntu.com/security/CVE-2026-77014 |
说明:补丁链接仅供初步排查参考,实际可用性请人工再次确认,补丁下载验证可使用CVE补丁工具。
若补丁不准确,烦请在此issue下评论 '/report-patch 参考网址 补丁链接1,补丁链接2' 反馈正确信息,便于我们不断优化工具,不胜感激。
如 /report-patch https://security-tracker.debian.org/tracker/CVE-2021-3997 https://github.com/systemd/systemd/commit/5b1cf7a9be37e20133c0208005274ce4a5b5c6a1


影响性分析说明:
A flaw was found in libsoup s SoupServer HTTP Range header processing. The sort_ranges() comparator in soup-message-headers.c truncates a 64-bit subtraction result to 32-bit int, flipping the sign for range offsets differing by more than INT_MAX. This causes silent omission of requested byte ranges from HTTP 206 Partial Content responses on resources larger than approximately 2 GB.
openEuler评分:
BaseScore:5.3 Medium
Vector:CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
受影响版本排查(受影响/不受影响):
1.master(3.7.2): 受影响
2.openEuler-20.03-LTS-SP4: 不受影响
3.openEuler-22.03-LTS-SP4: 不受影响
4.openEuler-24.03-LTS-Next(3.4.5): 受影响
5.openEuler-24.03-LTS-SP1(3.4.5):受影响
6.openEuler-24.03-LTS-SP3(3.4.5):受影响
7.openEuler-24.03-LTS-SP4(3.4.5):受影响
修复是否涉及abi变化(是/否):
1.master(3.7.2):否
2.openEuler-20.03-LTS-SP4:否
3.openEuler-22.03-LTS-SP4:否
4.openEuler-24.03-LTS-Next(3.4.5):否
5.openEuler-24.03-LTS-SP1(3.4.5):否
6.openEuler-24.03-LTS-SP3(3.4.5):否
7.openEuler-24.03-LTS-SP4(3.4.5):否
原因说明:
1.master(3.7.2):正常修复
2.openEuler-20.03-LTS-SP4:不受影响-组件不存在
3.openEuler-22.03-LTS-SP4:不受影响-组件不存在
4.openEuler-24.03-LTS-Next(3.4.5):正常修复
5.openEuler-24.03-LTS-SP1(3.4.5):正常修复
6.openEuler-24.03-LTS-SP3(3.4.5):正常修复
7.openEuler-24.03-LTS-SP4(3.4.5):正常修复


经过cve-manager解析,部分字段填写错误,如红色字体所示:
影响性分析说明:
A flaw was found in libsoup s SoupServer HTTP Range header processing. The sort_ranges() comparator ...
openEuler评分: (评分和向量)
(请填写此字段)
受影响版本排查(受影响/不受影响):
1.master:受影响
2.openEuler-20.03-LTS-SP4:不受影响
3.openEuler-22.03-LTS-SP4:不受影响
4.openEuler-24.03-LTS-Next:受影响
5.openEuler-24.03-LTS-SP1:受影响
6.openEuler-24.03-LTS-SP3:受影响
7.openEuler-24.03-LTS-SP4:受影响
修复是否涉及abi变化(是/否):
1.master:否
2.openEuler-20.03-LTS-SP4:否
3.openEuler-22.03-LTS-SP4:否
4.openEuler-24.03-LTS-Next:否
5.openEuler-24.03-LTS-SP1:否
6.openEuler-24.03-LTS-SP3:否
7.openEuler-24.03-LTS-SP4:否
原因说明:
1.master:正常修复
2.openEuler-20.03-LTS-SP4:不受影响-组件不存在
3.openEuler-22.03-LTS-SP4:不受影响-组件不存在
4.openEuler-24.03-LTS-Next:正常修复
5.openEuler-24.03-LTS-SP1:正常修复
6.openEuler-24.03-LTS-SP3:正常修复
7.openEuler-24.03-LTS-SP4:正常修复


@technology208 经过 cve-manager 解析, 已分析的内容如下表所示:
| 状态 | 分析项目 | 内容 |
|---|---|---|
| 已分析 | 1.影响性分析说明 | A flaw was found in libsoup s SoupServer HTTP Range header processing. The sort_ranges() comparator in soup-message-headers.c truncates a 64-bit subtraction result to 32-bit int, flipping the sign for range offsets differing by more than INT_MAX. This causes silent omission of requested byte ranges from HTTP 206 Partial Content responses on resources larger than approximately 2 GB. |
| 已分析 | 2.openEulerScore | 5.3 |
| 已分析 | 3.openEulerVector | AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N |
| 已分析 | 4.受影响版本排查 | master:受影响,openEuler-20.03-LTS-SP4:不受影响,openEuler-22.03-LTS-SP4:不受影响,openEuler-24.03-LTS-Next:受影响,openEuler-24.03-LTS-SP1:受影响,openEuler-24.03-LTS-SP3:受影响,openEuler-24.03-LTS-SP4:受影响 |
| 已分析 | 5.是否涉及abi变化 | master:否,openEuler-20.03-LTS-SP4:否,openEuler-22.03-LTS-SP4:否,openEuler-24.03-LTS-Next:否,openEuler-24.03-LTS-SP1:否,openEuler-24.03-LTS-SP3:否,openEuler-24.03-LTS-SP4:否 |
| 已分析 | 6.原因说明 | master:正常修复,openEuler-20.03-LTS-SP4:不受影响-组件不存在,openEuler-22.03-LTS-SP4:不受影响-组件不存在,openEuler-24.03-LTS-Next:正常修复,openEuler-24.03-LTS-SP1:正常修复,openEuler-24.03-LTS-SP3:正常修复,openEuler-24.03-LTS-SP4:正常修复 |
请确认分析内容的准确性, 确认无误后, 您可以进行后续步骤, 否则您可以继续分析.


经过cve-manager解析,部分分支PR未合入,如红色字体所示:
原因说明:
1.master:正常修复(PR未合入)
2.openEuler-20.03-LTS-SP4:不受影响-组件不存在
3.openEuler-22.03-LTS-SP4:不受影响-组件不存在
4.openEuler-24.03-LTS-Next:正常修复(PR未合入)
5.openEuler-24.03-LTS-SP1:正常修复(PR未合入)
6.openEuler-24.03-LTS-SP3:正常修复(PR未合入)
7.openEuler-24.03-LTS-SP4:正常修复(PR未合入)


/branches master openEuler-24.03-LTS-Next openEuler-24.03-LTS-SP1 openEuler-24.03-LTS-SP3 openEuler-24.03-LTS-SP4


CVE-2026-77014
是否需要修复:是
是否存在适配:否
上游社区补丁:https://gitlab.gnome.org/GNOME/libsoup/-/commit/e82c13ba03defcee10f981ac964f4d570b21a251.patch
https://gitlab.gnome.org/GNOME/libsoup/-/commit/6ece9e52d918cefa1e99b5f359a22b111bdced75.patch
https://gitlab.gnome.org/GNOME/libsoup/-/commit/546a59d218eadc2f1006d4d9ecf0042666b88113.patch
分支修复情况:
1.master(3.7.2): 已修复
PR:


CVE-2026-77014
是否需要修复:是
是否存在适配:是
上游社区补丁:https://gitlab.gnome.org/GNOME/libsoup/-/commit/e82c13ba03defcee10f981ac964f4d570b21a251.patch
https://gitlab.gnome.org/GNOME/libsoup/-/commit/6ece9e52d918cefa1e99b5f359a22b111bdced75.patch
https://gitlab.gnome.org/GNOME/libsoup/-/commit/546a59d218eadc2f1006d4d9ecf0042666b88113.patch
分支修复情况:
1.openEuler-24.03-LTS-SP3(3.4.5): 已修复
PR:
- openEuler-24.03-LTS-SP3: https://gitcode.com/src-openeuler/libsoup3/merge_requests/186


补丁适配报告 (CVE-2026-77014)
1. backport-CVE-2026-77014-1.patch
- 状态: 适配成功 (status=adapted)
- 置信度: medium
适配冲突说明
适配说明
- Context adapted for baseline 3.4.5:
- (1) is_all_valid variable inlined as local boolean (was introduced in prerequisite commit c1796442 but is just a variable, not class/inheritance)
- (2) removed if(cur.end<cur.start) check from if(*end) block to match patch context (was removed in prerequisite commit)
- (3) added #include <errno.h> for ERANGE checks
- (4) adjusted context lines: return status→return SOUP_STATUS_OK, #SoupServer retained (patch uses [class@Server] from newer GI syntax), typedef enum SOUP_HEADER_VALUE absent in baseline (context adjusted)
- (5) test hunks 8/10/11 skipped - depend on prerequisite test infrastructure (do_single_range 5-arg→7-arg signature change, request_single_range_by_string absent). Hunks 7/9/12/13/14 adapted. git apply --check passes on adapted patch.
完整代码 diff(原补丁 → 适配补丁)
libsoup/soup-message-headers-private.h
--- 原补丁/libsoup/soup-message-headers-private.h
+++ 适配补丁/libsoup/soup-message-headers-private.h
@@ -4,6 +4,6 @@
+#define MAX_RANGES 200
+
- typedef enum {
- SOUP_HEADER_VALUE_UNTRUSTED,
- SOUP_HEADER_VALUE_TRUSTED
+ gboolean soup_message_headers_append_untrusted_data (SoupMessageHeaders *hdrs,
+ const char *name,
+ const char *value);
libsoup/soup-message-headers.c
--- 原补丁/libsoup/soup-message-headers.c
+++ 适配补丁/libsoup/soup-message-headers.c
@@ -1,4 +1,12 @@
-@@ -1226,7 +1226,12 @@ sort_ranges (gconstpointer a, gconstpointer b)
+@@ -10,6 +10,7 @@
+ #endif
+
+ #include <string.h>
++#include <errno.h>
+
+ #include "soup-message-headers-private.h"
+ #include "soup.h"
+@@ -1142,7 +1143,12 @@ sort_ranges (gconstpointer a, gconstpointer b)
SoupRange *ra = (SoupRange *)a;
SoupRange *rb = (SoupRange *)b;
@@ -12,9 +20,17 @@
}
/* like soup_message_headers_get_ranges(), except it returns:
-@@ -1270,6 +1275,17 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
+@@ -1163,6 +1169,7 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
+ GArray *array;
+ char *spec, *end;
+ guint status = SOUP_STATUS_OK;
++ gboolean is_all_valid = TRUE;
+
+ if (!range || strncmp (range, "bytes", 5) != 0)
+ return status;
+@@ -1179,24 +1186,63 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
if (!range_list)
- return SOUP_STATUS_OK; /* invalid list */
+ return status;
+ /* Reject the header outright if it asks for more ranges than we are
+ * willing to serve, rather than answering with the whole body: a client
@@ -27,10 +43,9 @@
+ : SOUP_STATUS_OK;
+ }
+
- /* Loop through the ranges and modify the status accordingly. Default to
- * status 200 (OK, ignoring the ranges). Switch to status 206 (Partial
- * Content) if there is at least one partially valid range. Switch to
-@@ -1281,15 +1297,48 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
+ array = g_array_new (FALSE, FALSE, sizeof (SoupRange));
+ for (r = range_list; r; r = r->next) {
+ SoupRange cur;
spec = r->data;
if (*spec == '-') {
@@ -63,13 +78,14 @@
+ continue;
+ }
+ cur.start = (goffset) value;
-+
if (*end == '-')
end++;
-- if (*end)
+ if (*end) {
- cur.end = g_ascii_strtoull (end, &end, 10);
-- else
-+ if (*end) {
+- if (cur.end < cur.start) {
+- status = SOUP_STATUS_OK;
+- break;
+- }
+ errno = 0;
+ value = g_ascii_strtoull (end, &end, 10);
+
@@ -80,11 +96,10 @@
+ cur.end = G_MAXINT64;
+ else
+ cur.end = (goffset) value;
-+ } else
+ } else
cur.end = total_length - 1;
}
-
-@@ -1330,19 +1379,24 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
+@@ -1222,19 +1268,24 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
}
if (total_length) {
@@ -118,7 +133,7 @@
}
*ranges = (SoupRange *)array->data;
-@@ -1375,6 +1429,11 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
+@@ -1267,6 +1318,11 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
* Beware that even if given a @total_length, this function does not
* check that the ranges are satisfiable.
*
@@ -127,6 +142,6 @@
+ * [class@Server] answers such a request with
+ * %SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE.
+ *
- * [class@Server] has built-in handling for range requests. If your
+ * #SoupServer has built-in handling for range requests. If your
* server handler returns a %SOUP_STATUS_OK response containing the
* complete response body (rather than pausing the message and
tests/range-test.c
--- 原补丁/tests/range-test.c
+++ 适配补丁/tests/range-test.c
@@ -1,5 +1,5 @@
-@@ -3,6 +3,8 @@
- #include "config.h"
+@@ -1,6 +1,8 @@
+ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
#include "test-utils.h"
+#include "soup-message-headers-private.h"
@@ -7,30 +7,8 @@
GBytes *full_response;
int total_length;
-@@ -161,6 +163,21 @@ request_single_range_by_string (SoupSession *session, const char *uri,
- g_object_unref (msg);
- }
-
-+/* Like request_single_range_by_string(), but able to check the ranges of a
-+ * successful 206 as well. */
-+static void
-+request_single_range_by_string_full (SoupSession *session, const char *uri,
-+ const char *range, SoupStatus expected_status,
-+ int expected_start, int expected_end)
-+{
-+ SoupMessage *msg;
-+
-+ msg = soup_message_new ("GET", uri);
-+ soup_message_headers_replace (soup_message_get_request_headers (msg), "Range", range);
-+
-+ do_single_range (session, msg, 0, 0, expected_status, expected_start, expected_end);
-+}
-+
- static void
- do_multi_range (SoupSession *session, SoupMessage *msg,
- int expected_return_ranges)
-@@ -445,6 +462,290 @@ do_range_test (SoupSession *session, const char *uri,
- SOUP_STATUS_OK);
+@@ -333,6 +335,290 @@ do_range_test (SoupSession *session, const char *uri,
+ 20, 30);
}
+/* Tests for the Range parser itself. Unlike the tests above, these don't need
@@ -317,70 +295,12 @@
+ }
+}
+
- #ifdef HAVE_APACHE
static void
do_apache_range_test (void)
-@@ -473,6 +774,49 @@ server_handler (SoupServer *server,
- full_response);
- }
-
-+static void
-+do_libsoup_only_range_test (SoupSession *session, const char *uri)
-+{
-+ gsize full_response_length = g_bytes_get_size (full_response);
-+ GString *range;
-+ int i;
-+
-+ /* A suffix length at least as long as the body selects the whole body. */
-+ debug_printf (1, "Requesting (suffix range the length of the body) -%d\n",
-+ (int) full_response_length);
-+ request_single_range (session, uri,
-+ -((int) full_response_length), -1,
-+ SOUP_STATUS_PARTIAL_CONTENT, 0, -1);
-+
-+ debug_printf (1, "Requesting (suffix range longer than the body) -999999\n");
-+ request_single_range_by_string_full (session, uri, "bytes=-999999",
-+ SOUP_STATUS_PARTIAL_CONTENT, 0, -1);
-+
-+ debug_printf (1, "Requesting (suffix range overflowing gint64) -99999999999999999999\n");
-+ request_single_range_by_string_full (session, uri, "bytes=-99999999999999999999",
-+ SOUP_STATUS_PARTIAL_CONTENT, 0, -1);
-+
-+ /* A start which overflows gint64 is treated like any other start past
-+ * the end of the body.
-+ * https://gitlab.gnome.org/GNOME/libsoup/-/issues/535
-+ */
-+ debug_printf (1, "Requesting (start overflowing gint64) 9888888888888019900-\n");
-+ request_single_range_by_string (session, uri, "bytes=9888888888888019900-",
-+ SOUP_STATUS_OK);
-+
-+ /* More ranges than the server is willing to coalesce, which is
-+ * rejected rather than answered with the whole body.
-+ * https://gitlab.gnome.org/GNOME/libsoup/-/issues/538
-+ */
-+ debug_printf (1, "Requesting (more ranges than the limit)\n");
-+ range = g_string_new ("bytes=");
-+ for (i = 0; i < MAX_RANGES + 1; i++)
-+ g_string_append (range, i > 0 ? ",0-0" : "0-0");
-+ request_single_range_by_string (session, uri, range->str,
-+ SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE);
-+ g_string_free (range, TRUE);
-+}
-+
- static void
- do_libsoup_range_test (void)
{
-@@ -488,6 +832,7 @@ do_libsoup_range_test (void)
- base_uri = soup_test_server_get_uri (server, "http", NULL);
- base_uri_str = g_uri_to_string (base_uri);
- do_range_test (session, base_uri_str, TRUE, TRUE);
-+ do_libsoup_only_range_test (session, base_uri_str);
- g_uri_unref (base_uri);
- g_free (base_uri_str);
- soup_test_server_quit_unref (server);
-@@ -512,6 +857,8 @@ main (int argc, char **argv)
+@@ -394,6 +680,8 @@ main (int argc, char **argv)
+
g_test_add_func ("/ranges/apache", do_apache_range_test);
- #endif
g_test_add_func ("/ranges/libsoup", do_libsoup_range_test);
+ g_test_add_func ("/ranges/parsing", do_range_parsing_test);
+ g_test_add_func ("/ranges/count", do_range_count_test);
tests/server-mem-limit-test.c
--- 原补丁/tests/server-mem-limit-test.c
+++ 适配补丁/tests/server-mem-limit-test.c
@@ -93,6 +93,3 @@
int
main (int argc, char **argv)
{
---
-GitLab
-
2. backport-CVE-2026-77014-2.patch
- 状态: 适配成功 (status=adapted)
- 置信度: high
适配冲突说明
适配说明
- Hunk 2 (soup-message-headers.c:1570): context lines 'const char *header
- ' and 'g_return_val_if_fail (hdrs, FALSE)
- ' adapted to match patch-1 baseline which uses inline init 'const char *header = soup_message_headers_get_one_common (hdrs, SOUP_HEADER_CONTENT_RANGE)
- ' and 'if (!header || strncmp (header, "bytes ", 6) != 0)'. Actual change (goffset length
- → goffset first_pos, last_pos, length
- ) is identical. Hunk 4 (range-test.c:746): trailing context '#ifdef HAVE_APACHE' removed because patch 1 replaced conditional compilation with SOUP_TEST_SKIP_IF_NO_APACHE runtime check. Inserted test function content is identical to original. 4 of 6 hunks applied cleanly without any modification.
完整代码 diff(原补丁 → 适配补丁)
libsoup/soup-message-headers.c
--- 原补丁/libsoup/soup-message-headers.c
+++ 适配补丁/libsoup/soup-message-headers.c
@@ -1,4 +1,4 @@
-@@ -1548,6 +1548,30 @@ soup_message_headers_set_range (SoupMessageHeaders *hdrs,
+@@ -1431,6 +1431,30 @@ soup_message_headers_set_range (SoupMessageHeaders *hdrs,
soup_message_headers_set_ranges (hdrs, &range, 1);
}
@@ -29,7 +29,7 @@
/**
* soup_message_headers_get_content_range:
* @hdrs: a #SoupMessageHeaders
-@@ -1560,6 +1584,11 @@ soup_message_headers_set_range (SoupMessageHeaders *hdrs,
+@@ -1443,6 +1467,11 @@ soup_message_headers_set_range (SoupMessageHeaders *hdrs,
* @end, and @total_length. If the total length field in the header
* was specified as "*", then @total_length will be set to -1.
*
@@ -41,16 +41,16 @@
* Returns: %TRUE if @hdrs contained a "Content-Range" header
* containing a byte range which could be parsed, %FALSE otherwise.
**/
-@@ -1570,7 +1599,7 @@ soup_message_headers_get_content_range (SoupMessageHeaders *hdrs,
+@@ -1453,7 +1482,7 @@ soup_message_headers_get_content_range (SoupMessageHeaders *hdrs,
goffset *total_length)
{
- const char *header;
+ const char *header = soup_message_headers_get_one_common (hdrs, SOUP_HEADER_CONTENT_RANGE);
- goffset length;
+ goffset first_pos, last_pos, length;
char *p;
- g_return_val_if_fail (hdrs, FALSE);
-@@ -1583,25 +1612,34 @@ soup_message_headers_get_content_range (SoupMessageHeaders *hdrs,
+ if (!header || strncmp (header, "bytes ", 6) != 0)
+@@ -1462,25 +1491,34 @@ soup_message_headers_get_content_range (SoupMessageHeaders *hdrs,
header += 6;
while (g_ascii_isspace (*header))
header++;
tests/range-test.c
--- 原补丁/tests/range-test.c
+++ 适配补丁/tests/range-test.c
@@ -1,4 +1,4 @@
-@@ -746,6 +746,98 @@ do_range_count_test (void)
+@@ -619,6 +619,98 @@ do_range_count_test (void)
}
}
@@ -94,10 +94,10 @@
+ }
+}
+
- #ifdef HAVE_APACHE
static void
do_apache_range_test (void)
-@@ -859,6 +951,7 @@ main (int argc, char **argv)
+ {
+@@ -682,6 +774,7 @@ main (int argc, char **argv)
g_test_add_func ("/ranges/libsoup", do_libsoup_range_test);
g_test_add_func ("/ranges/parsing", do_range_parsing_test);
g_test_add_func ("/ranges/count", do_range_count_test);
@@ -105,6 +105,3 @@
ret = g_test_run ();
---
-GitLab
-
3. backport-CVE-2026-77014-3.patch
- 状态: 适配成功 (status=adapted)
- 置信度: high
适配冲突说明
适配说明
- Skipped 4 non-critical test hunks in tests/range-test.c (depend on missing prerequisite commit c1796442 test infrastructure: request_single_range_by_string, do_libsoup_only_range_test, 7-arg do_single_range)
- applied 3 source file hunks + 1 test data hunk
- replaced SOUP_HEADER_VALUE_TRUSTED with TRUE (enum not backported in baseline, 4th param of soup_message_headers_replace_common is gboolean trusted_value)
完整代码 diff(原补丁 → 适配补丁)
libsoup/server/http1/soup-server-message-io-http1.c
--- 原补丁/libsoup/server/http1/soup-server-message-io-http1.c
+++ 适配补丁/libsoup/server/http1/soup-server-message-io-http1.c
@@ -1,4 +1,4 @@
-@@ -257,6 +257,8 @@ handle_partial_get (SoupServerMessage *msg)
+@@ -258,6 +258,8 @@ handle_partial_get (SoupServerMessage *msg)
&ranges, &nranges);
if (status == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE) {
soup_server_message_set_status (msg, status, NULL);
libsoup/soup-message-headers-private.h
--- 原补丁/libsoup/soup-message-headers-private.h
+++ 适配补丁/libsoup/soup-message-headers-private.h
@@ -1,4 +1,4 @@
-@@ -42,5 +42,8 @@ gboolean soup_message_headers_header_contains_common (SoupMessageHeaders *hdr
+@@ -37,5 +37,8 @@ gboolean soup_message_headers_header_contains_common (SoupMessageHeaders *hdr
gboolean soup_message_headers_header_equals_common (SoupMessageHeaders *hdrs,
SoupHeaderName name,
const char *value);
libsoup/soup-message-headers.c
--- 原补丁/libsoup/soup-message-headers.c
+++ 适配补丁/libsoup/soup-message-headers.c
@@ -1,4 +1,4 @@
-@@ -1680,6 +1680,23 @@ soup_message_headers_set_content_range (SoupMessageHeaders *hdrs,
+@@ -1557,6 +1557,23 @@ soup_message_headers_set_content_range (SoupMessageHeaders *hdrs,
g_free (header);
}
@@ -15,7 +15,7 @@
+ g_return_if_fail (hdrs);
+
+ header = g_strdup_printf ("bytes */%" G_GINT64_FORMAT, total_length);
-+ soup_message_headers_replace_common (hdrs, SOUP_HEADER_CONTENT_RANGE, header, SOUP_HEADER_VALUE_TRUSTED);
++ soup_message_headers_replace_common (hdrs, SOUP_HEADER_CONTENT_RANGE, header, TRUE);
+ g_free (header);
+}
+
tests/range-test.c
--- 原补丁/tests/range-test.c
+++ 适配补丁/tests/range-test.c
@@ -1,43 +1,4 @@
-@@ -163,6 +163,38 @@ request_single_range_by_string (SoupSession *session, const char *uri,
- g_object_unref (msg);
- }
-
-+/* Asserts a 416 which also reports how long the resource really is, as
-+ * RFC 9110 §15.5.17 asks for. Kept out of do_range_test() because it makes a
-+ * claim about the response body length that other servers need not match.
-+ */
-+static void
-+request_unsatisfiable_range (SoupSession *session, const char *uri,
-+ const char *range)
-+{
-+ SoupMessage *msg;
-+ GBytes *body;
-+ char *expected;
-+
-+ msg = soup_message_new ("GET", uri);
-+ soup_message_headers_replace (soup_message_get_request_headers (msg), "Range", range);
-+
-+ debug_printf (1, " Range: %s\n", range);
-+
-+ body = soup_test_session_async_send (session, msg, NULL, NULL);
-+
-+ soup_test_assert_message_status (msg, SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE);
-+
-+ expected = g_strdup_printf ("bytes */%" G_GSIZE_FORMAT,
-+ g_bytes_get_size (full_response));
-+ g_assert_cmpstr (soup_message_headers_get_one (soup_message_get_response_headers (msg),
-+ "Content-Range"),
-+ ==, expected);
-+ g_free (expected);
-+
-+ g_clear_pointer (&body, g_bytes_unref);
-+ g_object_unref (msg);
-+}
-+
- /* Like request_single_range_by_string(), but able to check the ranges of a
- * successful 206 as well. */
- static void
-@@ -764,6 +796,9 @@ static const ContentRangeParsingTest content_range_parsing_tests[] = {
+@@ -637,6 +637,9 @@ static const ContentRangeParsingTest content_range_parsing_tests[] = {
{ "single byte", "bytes 0-0/1", TRUE, 0, 0, 1 },
{ "final byte", "bytes 99-99/100", TRUE, 99, 99, 100 },
{ "unknown total length", "bytes 0-9/*", TRUE, 0, 9, -1 },
@@ -47,41 +8,3 @@
{ "extra space after the unit", "bytes 0-9/10", TRUE, 0, 9, 10 },
{ "large but representable", "bytes 0-9223372036854775805/9223372036854775806",
TRUE, 0, 9223372036854775805, 9223372036854775806 },
-@@ -871,6 +906,7 @@ do_libsoup_only_range_test (SoupSession *session, const char *uri)
- {
- gsize full_response_length = g_bytes_get_size (full_response);
- GString *range;
-+ char *str;
- int i;
-
- /* A suffix length at least as long as the body selects the whole body. */
-@@ -896,6 +932,16 @@ do_libsoup_only_range_test (SoupSession *session, const char *uri)
- request_single_range_by_string (session, uri, "bytes=9888888888888019900-",
- SOUP_STATUS_OK);
-
-+ /* A 416 reports the length of the resource, so that a client which
-+ * guessed a range wrong can work out what to ask for instead.
-+ */
-+ debug_printf (1, "Requesting (unsatisfiable) past the end of the body\n");
-+ str = g_strdup_printf ("bytes=%d-%d",
-+ (int) full_response_length + 1,
-+ (int) full_response_length + 100);
-+ request_unsatisfiable_range (session, uri, str);
-+ g_free (str);
-+
- /* More ranges than the server is willing to coalesce, which is
- * rejected rather than answered with the whole body.
- * https://gitlab.gnome.org/GNOME/libsoup/-/issues/538
-@@ -904,8 +950,7 @@ do_libsoup_only_range_test (SoupSession *session, const char *uri)
- range = g_string_new ("bytes=");
- for (i = 0; i < MAX_RANGES + 1; i++)
- g_string_append (range, i > 0 ? ",0-0" : "0-0");
-- request_single_range_by_string (session, uri, range->str,
-- SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE);
-+ request_unsatisfiable_range (session, uri, range->str);
- g_string_free (range, TRUE);
- }
-
---
-GitLab
-


CVE-2026-77014
是否需要修复:是
是否存在适配:是
上游社区补丁:https://gitlab.gnome.org/GNOME/libsoup/-/commit/e82c13ba03defcee10f981ac964f4d570b21a251.patch
https://gitlab.gnome.org/GNOME/libsoup/-/commit/6ece9e52d918cefa1e99b5f359a22b111bdced75.patch
https://gitlab.gnome.org/GNOME/libsoup/-/commit/546a59d218eadc2f1006d4d9ecf0042666b88113.patch
分支修复情况:
1.openEuler-24.03-LTS-Next(3.4.5): 已修复
PR:
- openEuler-24.03-LTS-Next: https://gitcode.com/src-openeuler/libsoup3/merge_requests/187


补丁适配报告 (CVE-2026-77014)
1. backport-CVE-2026-77014-1.patch
- 状态: 适配成功 (status=adapted)
- 置信度: medium
适配冲突说明
适配说明
- 4 files modified. soup-message-headers-private.h: MAX_RANGES define inserted at adapted context (baseline has function declarations where patch expected typedef enum). soup-message-headers.c: ~86-line offset
- added #include <errno.h> (patch uses errno/ERANGE but baseline lacked it)
- declared gboolean is_all_valid=TRUE (patch uses it but baseline doesn't have it — set but never checked in visible hunks)
- preserved baseline's cur.end<cur.start check as 'continue' (upstream removed it but test 'end before start' expects SOUP_STATUS_OK for bytes=10-1, and test 'invalid ranges do not prevent valid ones' requires continue not break)
- overflow handling subsumes baseline's cur.end<cur.start for overflow cases but not logical end<start. tests/range-test.c: added includes + self-contained parsing/count tests (RangeParsingTest, check_parsed_ranges, do_range_parsing_test, do_range_count_test) + test registrations
- skipped 3 non-critical test hunks (request_single_range_by_string_full, do_libsoup_only_range_test, call in do_libsoup_range_test) depending on prerequisite do_single_range 7-param refactor not in this CVE patch. tests/server-mem-limit-test.c: applied as-is from original patch (clean apply).
完整代码 diff(原补丁 → 适配补丁)
libsoup/soup-message-headers-private.h
--- 原补丁/libsoup/soup-message-headers-private.h
+++ 适配补丁/libsoup/soup-message-headers-private.h
@@ -4,6 +4,6 @@
+#define MAX_RANGES 200
+
- typedef enum {
- SOUP_HEADER_VALUE_UNTRUSTED,
- SOUP_HEADER_VALUE_TRUSTED
+ gboolean soup_message_headers_append_untrusted_data (SoupMessageHeaders *hdrs,
+ const char *name,
+ const char *value);
libsoup/soup-message-headers.c
--- 原补丁/libsoup/soup-message-headers.c
+++ 适配补丁/libsoup/soup-message-headers.c
@@ -1,4 +1,12 @@
-@@ -1226,7 +1226,12 @@ sort_ranges (gconstpointer a, gconstpointer b)
+@@ -10,6 +10,7 @@
+ #endif
+
+ #include <string.h>
++#include <errno.h>
+
+ #include "soup-message-headers-private.h"
+ #include "soup.h"
+@@ -1142,7 +1143,12 @@ sort_ranges (gconstpointer a, gconstpointer b)
SoupRange *ra = (SoupRange *)a;
SoupRange *rb = (SoupRange *)b;
@@ -12,9 +20,17 @@
}
/* like soup_message_headers_get_ranges(), except it returns:
-@@ -1270,6 +1275,17 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
+@@ -1163,6 +1169,7 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
+ GArray *array;
+ char *spec, *end;
+ guint status = SOUP_STATUS_OK;
++ gboolean is_all_valid = TRUE;
+
+ if (!range || strncmp (range, "bytes", 5) != 0)
+ return status;
+@@ -1179,27 +1186,67 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
if (!range_list)
- return SOUP_STATUS_OK; /* invalid list */
+ return status;
+ /* Reject the header outright if it asks for more ranges than we are
+ * willing to serve, rather than answering with the whole body: a client
@@ -27,10 +43,9 @@
+ : SOUP_STATUS_OK;
+ }
+
- /* Loop through the ranges and modify the status accordingly. Default to
- * status 200 (OK, ignoring the ranges). Switch to status 206 (Partial
- * Content) if there is at least one partially valid range. Switch to
-@@ -1281,15 +1297,48 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
+ array = g_array_new (FALSE, FALSE, sizeof (SoupRange));
+ for (r = range_list; r; r = r->next) {
+ SoupRange cur;
spec = r->data;
if (*spec == '-') {
@@ -50,7 +65,6 @@
+ cur.start = 0;
+ else
+ cur.start = total_length + suffix_length;
-+
cur.end = total_length - 1;
} else {
- cur.start = g_ascii_strtoull (spec, &end, 10);
@@ -63,13 +77,14 @@
+ continue;
+ }
+ cur.start = (goffset) value;
-+
if (*end == '-')
end++;
-- if (*end)
+ if (*end) {
- cur.end = g_ascii_strtoull (end, &end, 10);
-- else
-+ if (*end) {
+- if (cur.end < cur.start) {
+- status = SOUP_STATUS_OK;
+- break;
+- }
+ errno = 0;
+ value = g_ascii_strtoull (end, &end, 10);
+
@@ -80,11 +95,15 @@
+ cur.end = G_MAXINT64;
+ else
+ cur.end = (goffset) value;
-+ } else
+ } else
cur.end = total_length - 1;
}
-
-@@ -1330,19 +1379,24 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
++ if (cur.end < cur.start)
++ continue;
+ if (*end) {
+ status = SOUP_STATUS_OK;
+ break;
+@@ -1222,19 +1269,24 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
}
if (total_length) {
@@ -118,15 +137,21 @@
}
*ranges = (SoupRange *)array->data;
-@@ -1375,6 +1429,11 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
+@@ -1265,9 +1317,14 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
+ * redundant.
+ *
* Beware that even if given a @total_length, this function does not
- * check that the ranges are satisfiable.
- *
-+ * A Range header requesting more than 200 ranges is rejected, since serving
-+ * that many ranges costs far more than the request asking for them.
-+ * [class@Server] answers such a request with
-+ * %SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE.
-+ *
- * [class@Server] has built-in handling for range requests. If your
+- * check that the ranges are satisfiable.
+- *
+- * #SoupServer has built-in handling for range requests. If your
++ * check that the ranges are satisfiable.
++ *
++ * A Range header requesting more than 200 ranges is rejected, since serving
++ * that many ranges costs far more than the request asking for them.
++ * [class@Server] answers such a request with
++ * %SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE.
++ *
++ * #SoupServer has built-in handling for range requests. If your
* server handler returns a %SOUP_STATUS_OK response containing the
* complete response body (rather than pausing the message and
+ * returning some of the response body later), and there is a Range
tests/range-test.c
--- 原补丁/tests/range-test.c
+++ 适配补丁/tests/range-test.c
@@ -1,5 +1,5 @@
-@@ -3,6 +3,8 @@
- #include "config.h"
+@@ -1,6 +1,8 @@
+ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
#include "test-utils.h"
+#include "soup-message-headers-private.h"
@@ -7,30 +7,8 @@
GBytes *full_response;
int total_length;
-@@ -161,6 +163,21 @@ request_single_range_by_string (SoupSession *session, const char *uri,
- g_object_unref (msg);
- }
-
-+/* Like request_single_range_by_string(), but able to check the ranges of a
-+ * successful 206 as well. */
-+static void
-+request_single_range_by_string_full (SoupSession *session, const char *uri,
-+ const char *range, SoupStatus expected_status,
-+ int expected_start, int expected_end)
-+{
-+ SoupMessage *msg;
-+
-+ msg = soup_message_new ("GET", uri);
-+ soup_message_headers_replace (soup_message_get_request_headers (msg), "Range", range);
-+
-+ do_single_range (session, msg, 0, 0, expected_status, expected_start, expected_end);
-+}
-+
- static void
- do_multi_range (SoupSession *session, SoupMessage *msg,
- int expected_return_ranges)
-@@ -445,6 +462,290 @@ do_range_test (SoupSession *session, const char *uri,
- SOUP_STATUS_OK);
+@@ -333,6 +335,291 @@ do_range_test (SoupSession *session, const char *uri,
+ 20, 30);
}
+/* Tests for the Range parser itself. Unlike the tests above, these don't need
@@ -317,70 +295,13 @@
+ }
+}
+
- #ifdef HAVE_APACHE
++
static void
do_apache_range_test (void)
-@@ -473,6 +774,49 @@ server_handler (SoupServer *server,
- full_response);
- }
-
-+static void
-+do_libsoup_only_range_test (SoupSession *session, const char *uri)
-+{
-+ gsize full_response_length = g_bytes_get_size (full_response);
-+ GString *range;
-+ int i;
-+
-+ /* A suffix length at least as long as the body selects the whole body. */
-+ debug_printf (1, "Requesting (suffix range the length of the body) -%d\n",
-+ (int) full_response_length);
-+ request_single_range (session, uri,
-+ -((int) full_response_length), -1,
-+ SOUP_STATUS_PARTIAL_CONTENT, 0, -1);
-+
-+ debug_printf (1, "Requesting (suffix range longer than the body) -999999\n");
-+ request_single_range_by_string_full (session, uri, "bytes=-999999",
-+ SOUP_STATUS_PARTIAL_CONTENT, 0, -1);
-+
-+ debug_printf (1, "Requesting (suffix range overflowing gint64) -99999999999999999999\n");
-+ request_single_range_by_string_full (session, uri, "bytes=-99999999999999999999",
-+ SOUP_STATUS_PARTIAL_CONTENT, 0, -1);
-+
-+ /* A start which overflows gint64 is treated like any other start past
-+ * the end of the body.
-+ * https://gitlab.gnome.org/GNOME/libsoup/-/issues/535
-+ */
-+ debug_printf (1, "Requesting (start overflowing gint64) 9888888888888019900-\n");
-+ request_single_range_by_string (session, uri, "bytes=9888888888888019900-",
-+ SOUP_STATUS_OK);
-+
-+ /* More ranges than the server is willing to coalesce, which is
-+ * rejected rather than answered with the whole body.
-+ * https://gitlab.gnome.org/GNOME/libsoup/-/issues/538
-+ */
-+ debug_printf (1, "Requesting (more ranges than the limit)\n");
-+ range = g_string_new ("bytes=");
-+ for (i = 0; i < MAX_RANGES + 1; i++)
-+ g_string_append (range, i > 0 ? ",0-0" : "0-0");
-+ request_single_range_by_string (session, uri, range->str,
-+ SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE);
-+ g_string_free (range, TRUE);
-+}
-+
- static void
- do_libsoup_range_test (void)
{
-@@ -488,6 +832,7 @@ do_libsoup_range_test (void)
- base_uri = soup_test_server_get_uri (server, "http", NULL);
- base_uri_str = g_uri_to_string (base_uri);
- do_range_test (session, base_uri_str, TRUE, TRUE);
-+ do_libsoup_only_range_test (session, base_uri_str);
- g_uri_unref (base_uri);
- g_free (base_uri_str);
- soup_test_server_quit_unref (server);
-@@ -512,6 +857,8 @@ main (int argc, char **argv)
+@@ -394,6 +681,8 @@ main (int argc, char **argv)
+
g_test_add_func ("/ranges/apache", do_apache_range_test);
- #endif
g_test_add_func ("/ranges/libsoup", do_libsoup_range_test);
+ g_test_add_func ("/ranges/parsing", do_range_parsing_test);
+ g_test_add_func ("/ranges/count", do_range_count_test);
tests/server-mem-limit-test.c
--- 原补丁/tests/server-mem-limit-test.c
+++ 适配补丁/tests/server-mem-limit-test.c
@@ -93,7 +93,3 @@
int
main (int argc, char **argv)
{
---
-GitLab
-
-
2. backport-CVE-2026-77014-2.patch
- 状态: 适配成功 (status=adapted)
- 置信度: high
适配冲突说明
适配说明
- Hunk 3 (soup-message-headers.c @@ -1570,7 +1599,7 @@): 2 context lines adapted to match current source after CVE-2026-77014 part 1 patch.
- (1) 'const char *header;' -> 'const char *header = soup_message_headers_get_one_common (hdrs, SOUP_HEADER_CONTENT_RANGE);' (part 1 inlined the header lookup).
- (2) 'g_return_val_if_fail (hdrs, FALSE);' -> 'if (!header || strncmp (header, "bytes ", 6) != 0)' (part 1 replaced g_return_val_if_fail with combined null+prefix check). Actual change preserved AS-IS: '-goffset length;' -> '+goffset first_pos, last_pos, length;'. Hunk 5 (tests/range-test.c @@ -746,6 +746,98 @@): 1 context line adapted: '#ifdef HAVE_APACHE' dropped (current source uses SOUP_TEST_SKIP_IF_NO_APACHE runtime macro at range-test.c:719). All 92 added lines (ContentRangeParsingTest struct, content_range_parsing_tests array, do_content_range_parsing_test function) preserved unchanged. Hunks 1, 2, 4, 6 preserved AS-IS — all context lines verified to match current source. Conflict: Adapt context.
完整代码 diff(原补丁 → 适配补丁)
libsoup/soup-message-headers.c
--- 原补丁/libsoup/soup-message-headers.c
+++ 适配补丁/libsoup/soup-message-headers.c
@@ -1,4 +1,4 @@
-@@ -1548,6 +1548,30 @@ soup_message_headers_set_range (SoupMessageHeaders *hdrs,
+@@ -1432,6 +1432,30 @@ soup_message_headers_set_range (SoupMessageHeaders *hdrs,
soup_message_headers_set_ranges (hdrs, &range, 1);
}
@@ -29,7 +29,7 @@
/**
* soup_message_headers_get_content_range:
* @hdrs: a #SoupMessageHeaders
-@@ -1560,6 +1584,11 @@ soup_message_headers_set_range (SoupMessageHeaders *hdrs,
+@@ -1444,6 +1468,11 @@ soup_message_headers_set_range (SoupMessageHeaders *hdrs,
* @end, and @total_length. If the total length field in the header
* was specified as "*", then @total_length will be set to -1.
*
@@ -41,16 +41,16 @@
* Returns: %TRUE if @hdrs contained a "Content-Range" header
* containing a byte range which could be parsed, %FALSE otherwise.
**/
-@@ -1570,7 +1599,7 @@ soup_message_headers_get_content_range (SoupMessageHeaders *hdrs,
+@@ -1454,7 +1483,7 @@ soup_message_headers_get_content_range (SoupMessageHeaders *hdrs,
goffset *total_length)
{
- const char *header;
+ const char *header = soup_message_headers_get_one_common (hdrs, SOUP_HEADER_CONTENT_RANGE);
- goffset length;
+ goffset first_pos, last_pos, length;
char *p;
- g_return_val_if_fail (hdrs, FALSE);
-@@ -1583,25 +1612,34 @@ soup_message_headers_get_content_range (SoupMessageHeaders *hdrs,
+ if (!header || strncmp (header, "bytes ", 6) != 0)
+@@ -1463,25 +1492,34 @@ soup_message_headers_get_content_range (SoupMessageHeaders *hdrs,
header += 6;
while (g_ascii_isspace (*header))
header++;
tests/range-test.c
--- 原补丁/tests/range-test.c
+++ 适配补丁/tests/range-test.c
@@ -1,4 +1,4 @@
-@@ -746,6 +746,98 @@ do_range_count_test (void)
+@@ -619,6 +619,97 @@ do_range_count_test (void)
}
}
@@ -93,11 +93,10 @@
+ soup_message_headers_unref (hdrs);
+ }
+}
-+
- #ifdef HAVE_APACHE
+
static void
do_apache_range_test (void)
-@@ -859,6 +951,7 @@ main (int argc, char **argv)
+@@ -683,6 +774,7 @@ main (int argc, char **argv)
g_test_add_func ("/ranges/libsoup", do_libsoup_range_test);
g_test_add_func ("/ranges/parsing", do_range_parsing_test);
g_test_add_func ("/ranges/count", do_range_count_test);
@@ -105,7 +104,3 @@
ret = g_test_run ();
---
-GitLab
-
-
3. backport-CVE-2026-77014-3.patch
- 状态: 适配成功 (status=adapted)
- 置信度: high
适配冲突说明
适配说明
- 3 of 6 hunks required adaptation. Hunk 3 (soup-message-headers.c): SOUP_HEADER_VALUE_TRUSTED→TRUE constant substitution — symbol absent in 3.4.5
- existing soup_message_headers_set_content_range at line 1557 already uses TRUE as 4th arg to soup_message_headers_replace_common. Hunk 4 (range-test.c): request_unsatisfiable_range function placed after request_single_range (line 111) instead of non-existent request_single_range_by_string. Hunk 5 (range-test.c): unsatisfied range test entry inserted after 'unknown total length' in content_range_parsing_tests[] (line numbers shifted due to previous patch). Hunk 6 (range-test.c): adapted from do_libsoup_only_range_test to do_range_test (line 232)
- char *str added to variable declarations
- request_unsatisfiable_range call inserted after invalid range test
- MAX_RANGES+1 loop sub-change skipped (context absent in 3.4.5 do_range_test). Hunks 1-2 (http1.c, private.h) applied as-is.
完整代码 diff(原补丁 → 适配补丁)
libsoup/server/http1/soup-server-message-io-http1.c
--- 原补丁/libsoup/server/http1/soup-server-message-io-http1.c
+++ 适配补丁/libsoup/server/http1/soup-server-message-io-http1.c
@@ -1,4 +1,4 @@
-@@ -257,6 +257,8 @@ handle_partial_get (SoupServerMessage *msg)
+@@ -258,6 +258,8 @@ handle_partial_get (SoupServerMessage *msg)
&ranges, &nranges);
if (status == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE) {
soup_server_message_set_status (msg, status, NULL);
libsoup/soup-message-headers-private.h
--- 原补丁/libsoup/soup-message-headers-private.h
+++ 适配补丁/libsoup/soup-message-headers-private.h
@@ -1,4 +1,4 @@
-@@ -42,5 +42,8 @@ gboolean soup_message_headers_header_contains_common (SoupMessageHeaders *hdr
+@@ -37,5 +37,8 @@ gboolean soup_message_headers_header_contains_common (SoupMessageHeaders *hdr
gboolean soup_message_headers_header_equals_common (SoupMessageHeaders *hdrs,
SoupHeaderName name,
const char *value);
libsoup/soup-message-headers.c
--- 原补丁/libsoup/soup-message-headers.c
+++ 适配补丁/libsoup/soup-message-headers.c
@@ -1,4 +1,4 @@
-@@ -1680,6 +1680,23 @@ soup_message_headers_set_content_range (SoupMessageHeaders *hdrs,
+@@ -1558,6 +1558,23 @@ soup_message_headers_set_content_range (SoupMessageHeaders *hdrs,
g_free (header);
}
@@ -15,7 +15,7 @@
+ g_return_if_fail (hdrs);
+
+ header = g_strdup_printf ("bytes */%" G_GINT64_FORMAT, total_length);
-+ soup_message_headers_replace_common (hdrs, SOUP_HEADER_CONTENT_RANGE, header, SOUP_HEADER_VALUE_TRUSTED);
++ soup_message_headers_replace_common (hdrs, SOUP_HEADER_CONTENT_RANGE, header, TRUE);
+ g_free (header);
+}
+
tests/range-test.c
--- 原补丁/tests/range-test.c
+++ 适配补丁/tests/range-test.c
@@ -1,5 +1,5 @@
-@@ -163,6 +163,38 @@ request_single_range_by_string (SoupSession *session, const char *uri,
- g_object_unref (msg);
+@@ -110,6 +110,38 @@ request_single_range (SoupSession *session, const char *uri,
+ do_single_range (session, msg, start, end, succeed);
}
+/* Asserts a 416 which also reports how long the resource really is, as
@@ -34,30 +34,20 @@
+ g_object_unref (msg);
+}
+
- /* Like request_single_range_by_string(), but able to check the ranges of a
- * successful 206 as well. */
static void
-@@ -764,6 +796,9 @@ static const ContentRangeParsingTest content_range_parsing_tests[] = {
- { "single byte", "bytes 0-0/1", TRUE, 0, 0, 1 },
- { "final byte", "bytes 99-99/100", TRUE, 99, 99, 100 },
- { "unknown total length", "bytes 0-9/*", TRUE, 0, 9, -1 },
-+ /* The unsatisfied-range form a 416 carries has no range to report, so
-+ * there is nothing this function can return for it. */
-+ { "unsatisfied range", "bytes */10", FALSE, 0, 0, 0 },
- { "extra space after the unit", "bytes 0-9/10", TRUE, 0, 9, 10 },
- { "large but representable", "bytes 0-9223372036854775805/9223372036854775806",
- TRUE, 0, 9223372036854775805, 9223372036854775806 },
-@@ -871,6 +906,7 @@ do_libsoup_only_range_test (SoupSession *session, const char *uri)
+ do_multi_range (SoupSession *session, SoupMessage *msg,
+ int expected_return_ranges)
+@@ -234,6 +266,7 @@ do_range_test (SoupSession *session, const char *uri,
{
- gsize full_response_length = g_bytes_get_size (full_response);
- GString *range;
+ gsize full_response_length = g_bytes_get_size (full_response);
+ int twelfths = full_response_length / 12;
+ char *str;
- int i;
- /* A suffix length at least as long as the body selects the whole body. */
-@@ -896,6 +932,16 @@ do_libsoup_only_range_test (SoupSession *session, const char *uri)
- request_single_range_by_string (session, uri, "bytes=9888888888888019900-",
- SOUP_STATUS_OK);
+ memset (test_response, 0, full_response_length);
+
+@@ -326,6 +359,16 @@ do_range_test (SoupSession *session, const char *uri,
+ full_response_length + 1, full_response_length + 100,
+ FALSE);
+ /* A 416 reports the length of the resource, so that a client which
+ * guessed a range wrong can work out what to ask for instead.
@@ -69,19 +59,16 @@
+ request_unsatisfiable_range (session, uri, str);
+ g_free (str);
+
- /* More ranges than the server is willing to coalesce, which is
- * rejected rather than answered with the whole body.
- * https://gitlab.gnome.org/GNOME/libsoup/-/issues/538
-@@ -904,8 +950,7 @@ do_libsoup_only_range_test (SoupSession *session, const char *uri)
- range = g_string_new ("bytes=");
- for (i = 0; i < MAX_RANGES + 1; i++)
- g_string_append (range, i > 0 ? ",0-0" : "0-0");
-- request_single_range_by_string (session, uri, range->str,
-- SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE);
-+ request_unsatisfiable_range (session, uri, range->str);
- g_string_free (range, TRUE);
- }
-
---
-GitLab
-
+ debug_printf (1, "Requesting (semi-invalid) 1-10,%d-%d,20-30\n",
+ (int) full_response_length + 1,
+ (int) full_response_length + 100);
+@@ -637,6 +680,9 @@ static const ContentRangeParsingTest content_range_parsing_tests[] = {
+ { "single byte", "bytes 0-0/1", TRUE, 0, 0, 1 },
+ { "final byte", "bytes 99-99/100", TRUE, 99, 99, 100 },
+ { "unknown total length", "bytes 0-9/*", TRUE, 0, 9, -1 },
++ /* The unsatisfied-range form a 416 carries has no range to report, so
++ * there is nothing this function can return for it. */
++ { "unsatisfied range", "bytes */10", FALSE, 0, 0, 0 },
+ { "extra space after the unit", "bytes 0-9/10", TRUE, 0, 9, 10 },
+ { "large but representable", "bytes 0-9223372036854775805/9223372036854775806",
+ TRUE, 0, 9223372036854775805, 9223372036854775806 },


经过cve-manager解析,部分分支PR未合入,如红色字体所示:
原因说明:
1.master:正常修复
2.openEuler-20.03-LTS-SP4:不受影响-组件不存在
3.openEuler-22.03-LTS-SP4:不受影响-组件不存在
4.openEuler-24.03-LTS-Next:正常修复
5.openEuler-24.03-LTS-SP1:正常修复(PR未合入)
6.openEuler-24.03-LTS-SP3:正常修复
7.openEuler-24.03-LTS-SP4:正常修复(PR未合入)


是否需要修复:未知
是否存在适配:否
上游社区补丁:无
分支修复情况:
1.openEuler-24.03-LTS-SP1(3.4.5): 分析失败


是否需要修复:未知
是否存在适配:否
上游社区补丁:无
分支修复情况:
1.openEuler-24.03-LTS-SP4(3.4.5): 分析失败


所有PR均已合入


一、漏洞信息
漏洞编号:CVE-2026-77014
漏洞归属组件:libsoup3
漏洞归属的版本:3.0.6,3.2.2,3.4.4,3.4.5,3.6.5,3.6.6
CVSS评分:
BaseScore:5.3 Medium
Vector:CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
漏洞简述:
A flaw was found in libsoup s SoupServer HTTP Range header processing. The sort_ranges() comparator in soup-message-headers.c truncates a 64-bit subtraction result to 32-bit int, flipping the sign for range offsets differing by more than INT_MAX. This causes silent omission of requested byte ranges from HTTP 206 Partial Content responses on resources larger than approximately 2 GB.
漏洞公开时间:2026-08-20 17:16:48
漏洞创建时间:2026-08-21 16:48:00
漏洞详情参考链接:
https://nvd.nist.gov/vuln/detail/CVE-2026-77014
更多参考(点击展开)
漏洞分析指导链接:
https://atomgit.com/openeuler/cve-manager/blob/master/cve-vulner-manager/doc/md/manual.md
漏洞数据来源:
七彩瞬析开源风险感知平台
漏洞补丁信息:
详情(点击展开)
无
二、漏洞分析结构反馈
影响性分析说明:
A flaw was found in libsoup s SoupServer HTTP Range header processing. The sort_ranges() comparator in soup-message-headers.c truncates a 64-bit subtraction result to 32-bit int, flipping the sign for range offsets differing by more than INT_MAX. This causes silent omission of requested byte ranges from HTTP 206 Partial Content responses on resources larger than approximately 2 GB.
openEuler评分:
5.3
Vector:CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
受影响版本排查(受影响/不受影响):
1.master(3.7.2):受影响
2.openEuler-20.03-LTS-SP4:不受影响
3.openEuler-22.03-LTS-SP4:不受影响
4.openEuler-24.03-LTS-Next(3.4.5):受影响
5.openEuler-24.03-LTS-SP1(3.4.5):受影响
6.openEuler-24.03-LTS-SP3(3.4.5):受影响
7.openEuler-24.03-LTS-SP4(3.4.5):受影响
修复是否涉及abi变化(是/否):
1.master(3.7.2):否
2.openEuler-20.03-LTS-SP4:否
3.openEuler-22.03-LTS-SP4:否
4.openEuler-24.03-LTS-Next(3.4.5):否
5.openEuler-24.03-LTS-SP1(3.4.5):否
6.openEuler-24.03-LTS-SP3(3.4.5):否
7.openEuler-24.03-LTS-SP4(3.4.5):否
原因说明:
1.master(3.7.2):正常修复
2.openEuler-20.03-LTS-SP4:不受影响-组件不存在
3.openEuler-22.03-LTS-SP4:不受影响-组件不存在
4.openEuler-24.03-LTS-Next(3.4.5):正常修复
5.openEuler-24.03-LTS-SP1(3.4.5):正常修复
6.openEuler-24.03-LTS-SP3(3.4.5):正常修复
7.openEuler-24.03-LTS-SP4(3.4.5):正常修复