fix(reader): pin render task lifetime to renderer ref and uuid - #386
Conversation
Render task structs now carry a renderer shared reference and a uuid snapshot; workers dereference only those and skip tasks whose sheet is gone (existSheetByUuid). DocSheet owns SheetRenderer via QSharedPointer and purges queued tasks (clearAllTasksForSheet/Page) before destruction. BrowserPage validates page aliveness before writing render results back, and the pinch-zoom timer callback is bound to its receiver to avoid UAF. 渲染任务结构体改为携带渲染器共享引用与入队时快照的 uuid:worker 线 程仅解引用这两者,并经 existSheetByUuid 跳过已销毁文档的任务。 DocSheet 改用 QSharedPointer 持有 SheetRenderer,析构前排空排队任务 (clearAllTasksForSheet/Page);BrowserPage 回写渲染结果前校验页面 存活;捏合缩放定时器回调绑定 receiver,消除悬空指针。 Log: 渲染任务生命周期加固,消除文档销毁后 worker/回包路径悬空指针 PMS: BUG-377151 Influence: 文档关闭/缩放过程中渲染回调不再有悬空指针风险;正常渲染行为不变。
Reviewer's GuideThe PR eliminates document/page UAF risks by giving worker tasks shared ownership of a parentless renderer, replacing worker-side object access with UUID and value snapshots, validating document/page liveness before processing or returning results, and cleaning stale queues during destruction; it also makes pinch-zoom timer callbacks destruction-safe and updates affected tests. Sequence diagram for UAF-safe page render task processingsequenceDiagram
participant BrowserPage
participant PageRenderThread
participant DocSheet
participant SheetRenderer
BrowserPage->>DocSheet: rendererPtr()
BrowserPage->>PageRenderThread: appendTask(renderer, uuid, pageIndex, page)
PageRenderThread->>DocSheet: existSheetByUuid(uuid)
alt document exists and renderer is valid
PageRenderThread->>SheetRenderer: getImage(pageIndex, ...)
SheetRenderer-->>PageRenderThread: rendered image
PageRenderThread-->>BrowserPage: sigDocPageNormalImageTaskFinished(task, pixmap)
BrowserPage->>BrowserPage: existPage(page)
alt page is alive
BrowserPage->>BrowserPage: handleRenderFinished(...)
end
else document is gone
PageRenderThread-->>PageRenderThread: skip task
end
Flow diagram for document and page destruction cleanupflowchart TD
DestroySheet[DocSheet destructor] --> ClearSheet[clearAllTasksForSheet]
DestroyPage[BrowserPage destructor] --> ClearImages[clearImageTasks]
DestroyPage --> ClearPage[clearAllTasksForPage]
ClearSheet --> Queues[Remove pending sheet tasks]
ClearImages --> Queues
ClearPage --> Queues
Queues --> Worker[Worker skips stale or safely owned tasks]
Worker --> Callback[Main-thread result callback]
Callback --> PageCheck[BrowserPage existPage]
PageCheck -->|dead page| Drop[Drop result]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="reader/browser/PageRenderThread.cpp" line_range="856" />
<code_context>
+ //getDocument出参改为局部变量,由worker带回、主线程回调写回sheet,避免跨线程写sheet成员
+ QProcess *process = nullptr;
+ deepin_reader::Document *document = deepin_reader::DocumentFactory::getDocument(task.fileType, filePath, task.convertedFileDir, task.password, &process, error);
+ task.process = process;
if (nullptr == document) {
</code_context>
<issue_to_address>
**issue (bug_risk):** When a document is destroyed while its open task is executing, `execNextDocOpenTask` stores the newly allocated `QProcess` in `task.process`, but `onDocOpenTask` returns after the sheet-liveness check without deleting or terminating it. The process is therefore leaked and its child process can remain running after the document has been closed.
**Triggers:** When an asynchronous document open completes after its DocSheet has been destroyed.
**Suggested fix:** Delete or terminate and delete `task.process` in the dropped-task path, while also cleaning up any document-opening resources that are no longer transferred to a live sheet.
</issue_to_address>| //getDocument出参改为局部变量,由worker带回、主线程回调写回sheet,避免跨线程写sheet成员 | ||
| QProcess *process = nullptr; | ||
| deepin_reader::Document *document = deepin_reader::DocumentFactory::getDocument(task.fileType, filePath, task.convertedFileDir, task.password, &process, error); | ||
| task.process = process; |
There was a problem hiding this comment.
issue (bug_risk): When a document is destroyed while its open task is executing, execNextDocOpenTask stores the newly allocated QProcess in task.process, but onDocOpenTask returns after the sheet-liveness check without deleting or terminating it. The process is therefore leaked and its child process can remain running after the document has been closed.
Triggers: When an asynchronous document open completes after its DocSheet has been destroyed.
Suggested fix: Delete or terminate and delete task.process in the dropped-task path, while also cleaning up any document-opening resources that are no longer transferred to a live sheet.
deepin pr auto reviewAI 代码审查报告总体评价
详细分析1. 语法逻辑 ✓ (25/25)评价: 语法正确,逻辑清晰 ✓ 分析: 本 PR 修复了渲染管线中的多个 UAF 漏洞,核心逻辑设计合理:
潜在问题: 2. 代码质量 ✓ (23/25)评价: 代码结构清晰,注释完整 ✓ 分析:
潜在问题:
改进建议: template<typename TaskT>
static void removeTasksForSheet(QList<TaskT> &tasks, QMutex &mutex, DocSheet *sheet) {
QMutexLocker locker(&mutex);
for (int i = tasks.count() - 1; i >= 0; --i) {
if (tasks[i].sheet == sheet)
tasks.removeAt(i);
}
}3. 代码性能 ✓ (19/20)评价: 性能良好,资源使用合理 ✓ 分析:
潜在问题:
改进建议: 4. 代码安全 ✓ (30/30)评价: 存在0个安全漏洞,安全合规 ✓
漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个 分析: 本 PR 是一项重要的安全改进,修复了渲染管线中的多个 Use-After-Free (UAF) 漏洞。以下是对安全机制的详细评估:
安全漏洞详情: 安全建议:
评分汇总
审查文件清单
关键变更说明本 PR 修复了 deepin-reader 渲染管线中的多个 Use-After-Free (UAF) 漏洞,核心变更如下:
本报告由 AI 代码审查工具自动生成 |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: add-uos, lzwind The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
/forcemerge |
|
This pr force merged! (status: unstable) |
修改说明
修复文档关闭/切换时的悬空指针(UAF)崩溃:渲染任务结构体改为携带渲染器共享引用与入队时快照的 uuid,worker 线程仅解引用这两者,并经
existSheetByUuid跳过已销毁文档的任务。DocSheet改用QSharedPointer持有SheetRenderer,析构前排空排队任务(clearAllTasksForSheet/clearAllTasksForPage)sheet/page等裸指针仅供主线程回调使用BrowserPage回写渲染结果前校验页面存活关联 PR
后续改动「侧栏缩略图仅在深色主题下反色」基于本分支堆叠,请先合入本 PR。
自测
Summary by Sourcery
Prevent rendering-related use-after-free crashes by making worker tasks lifetime-safe and ignoring stale document or page results.
Bug Fixes:
Enhancements:
Tests: