Skip to content

Commit daacc03

Browse files
committed
fix: prevent crashes from dangling pointers in destructors
1. Fixed null pointer dereference in DQuickWindowAttachedPrivate::destoryPlatformHandle() by adding null check before calling setEnabledNoTitlebarForWindow 2. Fixed event filter in DQuickWindowAttached to use window() instead of parent() to avoid accessing destroyed parent object 3. Added null check for window in DQuickWindowAttached::setAlphaBufferSize() to prevent accessing destroyed window 4. Added null checks in DQuickControlColorSelector palette handling to prevent crashes when items are destroyed 5. Added connection to QObject::destroyed signal to clear control and window pointers when control is destroyed 6. Changed m_control and m_controlWindow from raw pointers to QPointer for automatic nullification 7. Changed DQuickWindowAttachedPrivate::window from raw pointer to QPointer to prevent dangling pointer access Log: Fixed crashes caused by accessing destroyed objects during window and palette cleanup Influence: 1. Test window destruction scenarios to ensure no crashes occur 2. Verify palette functionality still works correctly with valid controls 3. Test window resize and minimize operations after palette changes 4. Verify alpha buffer size setting works with valid windows 5. Test rapid creation and destruction of windows with custom palettes 6. Verify no memory leaks occur with repeated window creation/ destruction fix: 修复析构导致的野指针崩溃问题 1. 在 DQuickWindowAttachedPrivate::destoryPlatformHandle() 中添加空指针 检查,避免在调用 setEnabledNoTitlebarForWindow 时访问已销毁对象 2. 修复 DQuickWindowAttached 中的事件过滤器,使用 window() 替代 parent() 避免访问已销毁的父对象 3. 在 DQuickWindowAttached::setAlphaBufferSize() 中添加窗口空指针检查, 防止访问已销毁的窗口 4. 在 DQuickControlColorSelector 调色板处理中添加空指针检查,防止控件销 毁时崩溃 5. 添加 QObject::destroyed 信号连接,在控件销毁时清除控制和窗口指针 6. 将 m_control 和 m_controlWindow 从原始指针改为 QPointer,实现自动置空 7. 将 DQuickWindowAttachedPrivate::window 从原始指针改为 QPointer,防止 悬垂指针访问 Log: 修复了窗口和调色板清理过程中访问已销毁对象导致的崩溃问题 Influence: 1. 测试窗口销毁场景,确保不会发生崩溃 2. 验证调色板功能在有效控件下仍能正常工作 3. 测试窗口调整大小和最小化操作后的调色板变化 4. 验证 alpha 缓冲区大小设置在有效窗口下正常工作 5. 测试快速创建和销毁带有自定义调色板的窗口 6. 验证重复窗口创建/销毁不会导致内存泄漏
1 parent 1aa2c93 commit daacc03

4 files changed

Lines changed: 25 additions & 11 deletions

File tree

src/dquickwindow.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2020 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: LGPL-3.0-or-later
44

@@ -173,7 +173,8 @@ bool DQuickWindowAttachedPrivate::ensurePlatformHandle()
173173

174174
void DQuickWindowAttachedPrivate::destoryPlatformHandle()
175175
{
176-
handle->setEnabledNoTitlebarForWindow(window, false);
176+
if (window)
177+
handle->setEnabledNoTitlebarForWindow(window, false);
177178
delete handle;
178179
handle = nullptr;
179180
}
@@ -1025,7 +1026,7 @@ void DQuickWindowAttached::setClipPath(QQuickPath *path)
10251026

10261027
bool DQuickWindowAttached::eventFilter(QObject *watched, QEvent *event)
10271028
{
1028-
if (watched == parent()) {
1029+
if (watched == window()) {
10291030
if (event->type() == QEvent::PlatformSurface) {
10301031
QPlatformSurfaceEvent *surface = static_cast<QPlatformSurfaceEvent *>(event);
10311032
if (surface->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) {
@@ -1045,6 +1046,8 @@ void DQuickWindowAttached::setAlphaBufferSize(int size)
10451046
return;
10461047

10471048
QQuickWindow *w = window();
1049+
if (!w)
1050+
return;
10481051
QSurfaceFormat fmt = w->requestedFormat();
10491052
fmt.setAlphaBufferSize(size);
10501053
w->setFormat(fmt);

src/private/dquickcontrolpalette.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,14 @@ static inline bool _d_isWindowRootItem(QQuickItem *item) {
6666
// `qvariant_cast` gets application's palette, and `toQPalette` gets root window's
6767
// palette.
6868
static inline QPalette _d_getControlPalette(QQuickItem *item) {
69+
if (!item)
70+
return QPalette();
71+
6972
const QVariant &palette = item->property("palette");
7073
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
7174
const QQuickPalette *pa = palette.value<QQuickPalette *>();
72-
Q_ASSERT(pa);
75+
if (!pa)
76+
return QPalette();
7377
return pa->toQPalette();
7478
#else
7579
return qvariant_cast<QPalette>(palette);
@@ -467,6 +471,10 @@ void DQuickControlColorSelector::setControl(QQuickItem *newControl)
467471
auto palette = m_control->property("palette").value<QQuickPalette*>();
468472
connect(palette, &QQuickPalette::changed, this, &DQuickControlColorSelector::updateControlTheme);
469473
#endif
474+
connect(m_control, &QObject::destroyed, this, [this] {
475+
m_controlWindow = nullptr;
476+
m_control = nullptr;
477+
});
470478
if (m_control->metaObject()->indexOfSignal("paletteChanged()") != -1) {
471479
connect(m_control, SIGNAL(paletteChanged()), this, SLOT(updateControlTheme()));
472480
}
@@ -1086,12 +1094,13 @@ void DQuickControlColorSelector::onPaletteDestroyed()
10861094

10871095
void DQuickControlColorSelector::updateControlWindow()
10881096
{
1089-
if (m_controlWindow == m_control->window())
1097+
QQuickWindow *window = m_control ? m_control->window() : nullptr;
1098+
if (m_controlWindow == window)
10901099
return;
10911100
if (m_controlWindow) {
10921101
m_controlWindow->disconnect(this);
10931102
}
1094-
m_controlWindow = m_control->window();
1103+
m_controlWindow = window;
10951104
if (m_controlWindow) {
10961105
connect(m_controlWindow, &QQuickWindow::activeChanged,
10971106
this, &DQuickControlColorSelector::updateControlState);

src/private/dquickcontrolpalette_p.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2020 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: LGPL-3.0-or-later
44

@@ -370,8 +370,8 @@ class DQuickControlColorSelector : public QObject
370370
void setSuperColorSelector(DQuickControlColorSelector *parent);
371371
void setFamilyPropertyParent(DQuickControlColorSelector *parent);
372372

373-
QQuickItem *m_control = nullptr;
374-
QQuickWindow *m_controlWindow = nullptr;
373+
QPointer<QQuickItem> m_control;
374+
QPointer<QQuickWindow> m_controlWindow;
375375
QPointer<DQuickControlColorSelector> m_superColorSelector;
376376
QPointer<DQuickControlColorSelector> m_parentOfFamilyProperty;
377377
typedef QPair<QByteArray, DQuickControlPalette*> ControlPaletteData;

src/private/dquickwindow_p.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2020 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: LGPL-3.0-or-later
44

@@ -9,6 +9,8 @@
99
#include <DObject>
1010
#include <DPlatformHandle>
1111

12+
#include <QPointer>
13+
1214
#include "dquickwindow.h"
1315

1416
DQUICK_BEGIN_NAMESPACE
@@ -52,7 +54,7 @@ class DQuickWindowAttachedPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate
5254
void _q_onPaletteChanged();
5355
#endif
5456

55-
QWindow *window = nullptr;
57+
QPointer<QWindow> window = nullptr;
5658
DPlatformHandle *handle = nullptr;
5759
BoolOptional explicitEnable {Invalid};
5860
BoolOptional explicitTranslucentBackground {Invalid};

0 commit comments

Comments
 (0)