fix: guard detail "More" button click against stale list access - #732
fix: guard detail "More" button click against stale list access#732GongHeng2017 wants to merge 1 commit into
Conversation
1. 修复 PageDetail::slotBtnClicked 未校验按钮查找命中即按下标访问 m_ListTextBrowser 的越界崩溃; 2. clearWidget 在 deleteLater 旧 DetailButton 前先 disconnect 其 clicked 信号,阻断刷新重建期间旧按钮延迟销毁仍派发点击的时间窗; 3. 修复 showDeviceInfo 中 m_ListDetailSeperator[lstInfo.size()-1] 同类越界(if(!device) continue 致链表短于 lstInfo.size()),改用 last() 并判空; ===================================== 1. fix out-of-bounds access in PageDetail::slotBtnClicked where the button lookup result was not validated before indexing m_ListTextBrowser; 2. disconnect DetailButton::clicked before deleteLater in clearWidget to block stale clicks delivered during the deferred-deletion window after a refresh rebuild; 3. fix parallel out-of-bounds in showDeviceInfo where m_ListDetailSeperator[lstInfo.size()-1] could exceed list length when null devices were skipped, now uses last() with an empty check; Log: 修复扩展模式(多显示器)下点击显示设备“更多”按钮偶发闪退问题,根因为刷新重建页面时旧按钮延迟销毁期间其点击派发到已清空的按钮列表导致越界访问,通过校验查找命中与断开旧按钮信号根治 Bug: https://pms.uniontech.com/bug-view-308175.html
There was a problem hiding this comment.
Sorry @GongHeng2017, you have reached your weekly rate limit of 500000 diff characters.
Please try again later or upgrade to continue using Sourcery
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: GongHeng2017 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 |
Reviewer's guide (collapsed on small PRs)Reviewer's GuideGuard PageDetail’s "More" button handling against stale widgets and list index mismatches to prevent SEGVs, and fix a related separator visibility out-of-bounds access in multi-device views. Sequence diagram for guarded DetailButton click handlingsequenceDiagram
actor User
participant DetailButton
participant PageDetail
participant TextBrowser
User->>DetailButton: clicked
DetailButton->>PageDetail: slotBtnClicked
PageDetail->>PageDetail: qobject_cast DetailButton sender
alt [button is null]
PageDetail-->>PageDetail: return
else [button is non-null]
PageDetail->>PageDetail: m_ListDetailButton.indexOf button
alt [index < 0 or index >= m_ListTextBrowser.size]
PageDetail-->>PageDetail: return (ignore stale click)
else [index valid]
PageDetail->>DetailButton: updateText
PageDetail->>TextBrowser: updateShowOtherInfo
end
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
deepin pr auto review★ 总体评分:95分■ 【总体评价】
■ 【详细分析】
■ 【改进建议代码示例】 diff --git a/deepin-devicemanager/src/Page/PageDetail.cpp b/deepin-devicemanager/src/Page/PageDetail.cpp
index eb214322..improved_version 100644
--- a/deepin-devicemanager/src/Page/PageDetail.cpp
+++ b/deepin-devicemanager/src/Page/PageDetail.cpp
@@ -360,10 +360,10 @@ void PageDetail::clearWidget()
QList<DetailButton *> listDetailButton = m_ListDetailButton;
m_ListDetailButton.clear();
- // 清空DetailButton,先断开clicked信号,避免延迟销毁期间旧按钮仍派发点击到slotBtnClicked
+ // 清空DetailButton,先断开信号避免延迟销毁期间旧按钮派发事件
foreach (auto widget, listDetailButton) {
disconnect(widget, &DetailButton::clicked, this, &PageDetail::slotBtnClicked);
widget->deleteLater();
- widget = nullptr;
}
+ |
根因分析
扩展模式(≥2 显示器)下显示设备页经
PageInfoWidget::updateTable选中多设备页PageMultiInfo → PageDetail,其"更多"按钮DetailButton(tr("More"))的槽PageDetail::slotBtnClicked(src/Page/PageDetail.cpp:393)用foreach+break在m_ListDetailButton查按钮下标,未校验是否命中即m_ListTextBrowser[index](:410)取TextBrowser;命中失败时index==size()越界读得野指针 →browser->updateShowOtherInfo()解引用 → SEGV。触发机理:刷新(启动
DBus refreshInfo+singleShot(2000)/ 右键刷新 / 切页 / 扩展模式显示配置变化)走MainWindow::refresh → DeviceWidget::clear → PageDetail::clearWidget;clearWidget自ae0fff23(Bug-162167) 起为「先清空成员链表、再对副本deleteLater」——成员链表已空、旧按钮延迟销毁仍存活的时间窗内,其clicked派发到slotBtnClicked→ 空链表越界 → SEGV。与core.txt回溯QAbstractButton::clicked → activate → 3 帧自身代码 → SEGV及"仅扩展模式 / 闪退一次 / 概率性"现象一致。关键证据:
PageDetail.cpp:399-404,410— 查找无命中校验 + 越界m_ListTextBrowser[index]。PageInfoWidget.cpp:56-76—lst.size()>=2且非 BIOS →PageMultiInfo/PageDetail(扩展模式专属路径,区别于单屏PageSingleInfo/DetailTreeView)。log/core.txt—#4 QAbstractButton::clicked → #3 activate → #0..#2 deepin-devicemanager 自身。修复方案
slotBtnClicked用m_ListDetailButton.indexOf(button)替换foreach+break,命中且index < m_ListTextBrowser.size()才继续,否则return(忽略过期/空链表点击)。clearWidget在deleteLater()旧DetailButton前disconnect其clicked信号,从根源阻断「链表已空、旧按钮延迟销毁仍派发点击」的时间窗。showDeviceInfo的m_ListDetailSeperator[lstInfo.size()-1]同类越界(if(!device) continue致链表短于lstInfo.size()),改用m_ListDetailSeperator.last()并判空。改动安全评估
低风险。三处改动均在
PageDetail.cpp,无函数签名变更、无公开 API 变更、无删除公开成员。slotBtnClicked仅PageDetail.h声明 +ut_pagedetail.cpp:147直接调用(无 sender、空链表场景):保留if(!button) return守卫在前,行为不变、既有 UT 仍通过。clearWidget/showDeviceInfo调用者(PageMultiInfo)无感知。正常路径行为不变,仅修正「过期点击越界」「null 设备越界」两条异常路径(由崩溃→安全忽略)。关联
develop/eagle @ ccd4ab90,本 commit 直接基于该基线analysis-report.md;根因复核通过Summary by Sourcery
Guard PageDetail "More" button handling against stale widgets to prevent crashes when refreshing device info in multi-display mode.
Bug Fixes: