Repository navigation
fix(web): * 不得覆盖 Accept-Encoding 里显式给出的 q=0 - #10
Merged
Merged
Conversation
`parse_accept_encoding` 对 `q=0` 只是 `continue` 跳过,没有记下"这个编码被
显式拒了",于是 `*` 那一支又把它选回来,而且 `*` 默认 q=1.0、优先级还最高。
RFC 9110 §12.5.3 里 `*` 只匹配**没有显式列出**的编码,所以客户端发
`*, gzip;q=0` 会收到 gzip —— 一个它刚声明过收不了的编码。
修法:
- 记下被显式拒掉的编码,`*` 选择时避开;
- 收尾再加一道,挡住 `gzip;q=0, gzip;q=0.5` 这种自相矛盾输入把 gzip 选回来。
仓库里既有的 `"gzip;q=0, deflate"` 用例抓不到这条:它靠的是 deflate 显式出现
且 q 更高;只有两侧都仅由 `*` 覆盖时才露出来。已补 4 条用例。
变异验证(同一条断言、只换 DLL):
未修正 -> 3 条 FAIL(第 4 条 `*, deflate;q=0` 两边都过,它不区分,作用是
挡住"把 deflate 也一起拒掉"这种过度修正)
修正后 -> 10/10 PASS,5 条既有断言两边都绿(未碰既有行为)
Owner
|
核过了,
但收尾那一道会把同一类错误换个形状带回来,而且正好落在你写下的那条原则上 没有 ( 收紧的办法:收尾那道只退回到本身可接受的编码,也就是"显式列出且 q>0" 如果你改,我这边等这个 PR 更新;不想再动它的话说一声,我合进去之后自己补一条 其余部分我这边没有别的意见,CI 也是绿的。 |
Antruly
added a commit
that referenced
this pull request
Sep 19, 2026
`*_ok` 的语义是"没被 `q=0` 显式拒过",**不等于**"被接受了":没有 `*` 的时候, 未被列出的编码默认不可接受(RFC 9110 §12.5.3)。拿前者当后者用,就会给一个 只列了 gzip 的客户端发 `content-encoding: deflate` —— #10 修掉的那类错误换个 形状又回来了(`gzip;q=0, gzip;q=0.5` 会被选回 gzip)。 收尾判据改成一条:**退回的目标必须本身可接受** —— "显式列出且 q>0" 或 "被 `*` 覆盖到",两个都不满足就是 `NONE`。顺带把 `*;q=0` 带对了:它原来是被 整条跳过,按 RFC 应当读作"未列出的一律不可接受"。 Co-Authored-By: Claude Code <noreply@anthropic.com>
Antruly
added a commit
that referenced
this pull request
Sep 19, 2026
新增五条:自相矛盾的显式拒绝(`gzip;q=0, gzip;q=0.5`)、只拒一个、 `*;q=0`、`*;q=0` 加显式 gzip。 两个方向的变异都实测撞红,不是推理: - 收尾退回 `gzip_ok` 单独用(= #10 那一版的语义)→ accept_encoding FAIL; - 收紧过头成 `gzip_ok && wildcard` → 函数开头那三条反向守卫(`gzip`/`*`/`deflate` 照常选中)FAIL,所以反向守卫不在这里重复。 Co-Authored-By: Claude Code <noreply@anthropic.com>
Antruly
added a commit
that referenced
this pull request
Sep 19, 2026
Co-Authored-By: Claude Code <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
parse_accept_encoding对q=0的处理是if (q == 0.0) continue;—— 只是跳过这一项,没有记下"这个编码被显式拒了"。于是后面*那一支method = GZIP又把它选回来,而且*的 q 默认 1.0,优先级还最高。RFC 9110 §12.5.3:
也就是说
*管不着显式列出的编码。现状是客户端发一个"gzip 我收不了",服务端回 gzip:Accept-Encoding*, gzip;q=0gzip;q=0, **, gzip;q=0, deflate;q=0*, deflate;q=0仓库里既有的用例为什么没抓到
web_http_client_func.cpp里那条它成立靠的是"deflate 显式出现、且 q 更高"—— 两侧都只由
*覆盖时才会露出来。补的 4 条正好走那条缝。修法
q=0那一支把编码记进gzip_ok/deflate_ok,*选择时避开;q=0是"直接跳过",所以gzip;q=0, gzip;q=0.5这种自相矛盾输入仍会把 gzip 选回来。显式拒绝优先:少发一层编码只是没优化,发错一层编码是客户端解不开。
验证
变异验证(同一条断言、只换 DLL,不只看时间戳 —— 比过 md5):
parse_accept_encoding第 4 条用例(
*, deflate;q=0→ gzip)两边都过,它不区分。留着是作为反向守卫:挡住"把 deflate 也一起拒掉"这种过度修正。写在这里免得它被当成分辨性用例。另有端到端证据:开了压缩的靶场上,
Accept-Encoding: *, gzip;q=0的响应头从content-encoding: gzip变成deflate。一个顺带说明
同一轮还发现 HEAD 与 GET 在压缩下的头不一致(HEAD 报未压缩长度、GET 发压缩体,照 HEAD 读的客户端会挂住)。那条不在这个 PR 里 —— 根因在 webapp 层(长度在压缩发生之前就被
set_head_only/ 静态层的need_data = !is_head钉死了),修法要动设计,我在 issue 里另开一条,想先听你的意见。