Repository navigation
fix(http3): 帧回调里析构 WebSocket 会话后不再解下一帧(h3/h2) - #65
Merged
Merged
Conversation
`uvcpp_h3_ws_connection::on_data` 把一批数据里的每一帧依次交给解析器;帧回调 属于应用代码,在里面删掉这条会话是合法用法(应用收到一条错误帧就把整条会话 收摊)。旧实现在回调返回后继续解下一帧:此时对象已经析构,`uvcpp_ws_parser` 的析构把 `frame_arg_` 清成 nullptr,而 `frame_fn_` 仍是 `trampoline_frame`, 于是崩在 `trampoline_frame` 对空参数的第一次解引用上。 同一类问题在 h2 那条腿上也存在:`on_frame` 的 `message_.clear()`、`fail()` 里 的 `on_error` 都排在回调之后,一并调整了顺序。 - h3/h2 的 ws 会话各持一枚自己的存活令牌(`alive_`),析构第一件事置位; `on_data` 每解完一帧只看令牌,不再碰 `this`。 - `on_frame` 先把消息 swap 出成员再回调,回调之后不碰任何成员。 - `fail()` 先发 Close、置状态,最后才调 `on_error`。 测试:`test_http3_ws_func` 与 `test_h2_ws_func` 各加一条 destroy 场景 —— 两条 文本帧一次写进同一条流,服务端在第一帧的回调里销毁会话。去掉上面的守卫时两条 用例都在 `trampoline_frame` 处 SIGSEGV;加上后第二帧被丢弃、进程不崩。 全量 ctest 163/163。
Antruly
added a commit
that referenced
this pull request
Oct 29, 2026
- 版本头 PATCH 1;两版 README 的徽章与 Version 行同步,"最新版本"改为 v1.9.1。 - CHANGELOG:三条主题条目(WebSocket 语义 / 横向扩展 / TLS 与网络)+ 新增 v1.9.1 小节;当前源码树与 tag 清单同步。 - RELEASE.md:新增「v1.9.1 重点」,破坏性为**无**(只新增 API,C ABI 仍为 1)。 含自 v1.9.0 以来的三笔:#65(h3/h2 WS 帧回调里析构会话后的 UAF)、 #60(`uvcpp_udp_server(uvcpp_loop*)`,#59)、#57(五个 set_ssl_context 入口的 生命周期文档,issue #56),以及 `_local_deps` 误提交链接的清理。 本地:build-all 162/162、build-h3 120/120、build-default 60/60;文档门禁全绿; release_notes.py --tag v1.9.1 能切出正文。
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.
问题
uvcpp_h3_ws_connection::on_data会连续解同一批数据里的多帧。帧回调是应用代码,在里面删掉这条会话是合法用法(收到一条错误帧就整条会话收摊)。旧实现在回调
返回后继续解下一帧,而这时对象已经析构:
uvcpp_ws_parser的析构把frame_arg_清成nullptr,frame_fn_仍是trampoline_frame;trampoline_frame,第一句就是cmpq $0x0,0x10(%rsi),rsi == 0→ SIGSEGV。
现场栈(moLink 的 relay 客户端,两帧落在同一次 QUIC 流读取里):
修复
alive_),析构第一件事置位;on_data每解完一帧只看令牌,回调里析构了就立刻返回,不再碰this。on_frame先把消息 swap 出成员再回调(旧写法回调之后还有message_.clear(),同样是在已释放对象上)。
fail()先发 Close、置状态,最后才调on_error(旧写法回调在最前面,之后还会碰
close_sent_/h3_/closed_)。测试
两条 functional 用例,形状与生产崩溃一致:客户端把两条文本帧一次写进同一条
流,服务端在第一帧的
on_text里销毁会话。test_http3_ws_funcdestroytrampoline_frametest_h2_ws_funcdestroytrampoline_frame全量
ctest:163/163 通过(含 http3 / h2 / quic / webtransport)。备注
master(当前默认分支)。dev/1.9.0领先master4 个提交(v1.9.0 标签那批),合并后那条线需要一次合并或 cherry-pick 才能拿到这个修复。
约定(
uvcpp_ws_connection::alive_token_)在库内兜住,两种写法不冲突。