已关闭
CVE-2026-77014 #64
openeuler-ci-bot创建于  17 天前关闭于  13 天前
openeuler-ci-bot
openeuler-ci-bot成员
17 天前 创建

一、漏洞信息
漏洞编号: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://bugzilla.redhat.com/show_bug.cgi?id=2520143
https://security-tracker.debian.org/tracker/CVE-2026-77014
https://advisory.echohq.com/cve/CVE-2026-77014
https://gitlab.gnome.org/GNOME/libsoup/-/merge_requests/550
https://access.redhat.com/security/cve/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):正常修复

likedislike
openeuler-ci-botopeneuler-ci-bot成员
17 天前 添加了label:CVE/UNFIXED
openeuler-ci-bot
openeuler-ci-bot成员
17 天前 评论:

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

likedislike
openeuler-ci-botopeneuler-ci-bot成员
17 天前 添加了label:sig/GNOME
openeuler-ci-bot
openeuler-ci-bot成员
17 天前 评论:

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 .

likedislike
openeuler-ci-bot
openeuler-ci-bot成员
17 天前 评论:
参考网址 关联pr 状态 补丁链接
https://www.opencve.io/cve/CVE-2026-77014https://gitlab.gnome.org/GNOME/libsoup/-/merge_requests/550None
https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2026-77014
https://security-tracker.debian.org/tracker/CVE-2026-77014NoneNonehttps://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-77014https://gitlab.gnome.org/GNOME/libsoup/-/merge_requests/550None
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

likedislike
openeuler-ci-botopeneuler-ci-bot成员
17 天前 修改了issue 的描述
openeuler-ci-botopeneuler-ci-bot成员
17 天前 修改了issue 的描述
technology208成员
17 天前 评论:

影响性分析说明:
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):正常修复

likedislike
openeuler-ci-botopeneuler-ci-bot成员
17 天前 修改了issue 的描述
openeuler-ci-bot
openeuler-ci-bot成员
17 天前 评论:

经过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:正常修复

likedislike
openeuler-ci-botopeneuler-ci-bot成员
16 天前 修改了issue 的描述
openeuler-ci-bot
openeuler-ci-bot成员
16 天前 评论:

@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:正常修复

请确认分析内容的准确性, 确认无误后, 您可以进行后续步骤, 否则您可以继续分析.

likedislike
openeuler-ci-bot
openeuler-ci-bot成员
16 天前 评论:

经过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未合入)

likedislike
openeuler-ci-botopeneuler-ci-bot成员
16 天前 issue状态由 待办的 改变为 进行中
technology208成员
16 天前 评论:
openeuler-ci-botopeneuler-ci-bot成员
16 天前 修改了issue 的描述
lw5202031成员
14 天前 评论:

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

likedislike
openeuler-ci-botopeneuler-ci-bot成员
13 天前 修改了issue 的描述
xiaoo_robot
xiaoo_robot
13 天前 评论:

正在自动化处理任务,任务编号:TASK-gitcode__libsoup3-64-20260826092842-0,指定分支:master

✅ 任务结束 (用时: 17分钟)

likedislike
xiaoo_robot
xiaoo_robot
13 天前 评论:

正在自动化处理任务,任务编号:TASK-gitcode__libsoup3-64-20260826092843-1,指定分支:openEuler-24.03-LTS-Next

✅ 任务结束 (用时: 131分钟)

likedislike
xiaoo_robot
xiaoo_robot
13 天前 评论:

正在自动化处理任务,任务编号:TASK-gitcode__libsoup3-64-20260826092843-2,指定分支:openEuler-24.03-LTS-SP1

✅ 任务结束 (用时: 161分钟)

likedislike
xiaoo_robot
xiaoo_robot
13 天前 评论:

正在自动化处理任务,任务编号:TASK-gitcode__libsoup3-64-20260826092844-3,指定分支:openEuler-24.03-LTS-SP3

✅ 任务结束 (用时: 101分钟)

likedislike
xiaoo_robot
xiaoo_robot
13 天前 评论:

正在自动化处理任务,任务编号:TASK-gitcode__libsoup3-64-20260826092844-4,指定分支:openEuler-24.03-LTS-SP4

✅ 任务结束 (用时: 167分钟)

likedislike
xiaoo_robotxiaoo_robot
13 天前 关联了pull request:fix: CVE-2026-77014 - master
xiaoo_robotxiaoo_robot
13 天前 关联了pull request:fix: CVE-2026-77014 - openEuler-24.03-LTS-SP3
xiaoo_robot
xiaoo_robot
13 天前 评论:
xiaoo_robot
xiaoo_robot
13 天前 评论:

补丁适配报告 (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
-
likedislike
xiaoo_robotxiaoo_robot
13 天前 关联了pull request:fix: CVE-2026-77014 - openEuler-24.03-LTS-Next
xiaoo_robot
xiaoo_robot
13 天前 评论:
xiaoo_robot
xiaoo_robot
13 天前 评论:

补丁适配报告 (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 },
likedislike
openeuler-ci-botopeneuler-ci-bot成员
13 天前 关闭了 issue
openeuler-ci-bot
openeuler-ci-bot成员
13 天前 评论:

经过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未合入)

likedislike
openeuler-ci-botopeneuler-ci-bot成员
13 天前 重新打开了 issue
xiaoo_robot
xiaoo_robot
13 天前 评论:

是否需要修复:未知
是否存在适配:否
上游社区补丁:无

分支修复情况:
1.openEuler-24.03-LTS-SP1(3.4.5): 分析失败

likedislike
xiaoo_robot
xiaoo_robot
13 天前 评论:

是否需要修复:未知
是否存在适配:否
上游社区补丁:无

分支修复情况:
1.openEuler-24.03-LTS-SP4(3.4.5): 分析失败

likedislike
openeuler-ci-botopeneuler-ci-bot成员
13 天前 关联了pull request:[sync] PR-187: fix: CVE-2026-77014 - openEuler-24.03-LTS-Next
openeuler-ci-botopeneuler-ci-bot成员
13 天前 关联了pull request:[sync] PR-187: fix: CVE-2026-77014 - openEuler-24.03-LTS-Next
openeuler-ci-botopeneuler-ci-bot成员
13 天前 关闭了 issue
openeuler-ci-bot
openeuler-ci-bot成员
13 天前 评论:

所有PR均已合入

likedislike
openeuler-ci-botopeneuler-ci-bot成员
13 天前 issue状态由 进行中 改变为 已完成
openeuler-ci-botopeneuler-ci-bot成员
13 天前 删除了label:CVE/UNFIXED
openeuler-ci-botopeneuler-ci-bot成员
13 天前 添加了label:CVE/FIXED