aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMitch Curtis <mitch.curtis@qt.io>2020-10-14 11:06:01 +0200
committerMitch Curtis <mitch.curtis@qt.io>2020-10-19 09:32:38 +0200
commitd08bce267f2d7cba474a05d73869bc99fbd8d971 (patch)
tree6c8603b9a281334e36874f3728e58f676f828439
parent0f3df189e57d4c2bddce09380bbed8e0ed1fe2b7 (diff)
QQuickShaderEffect: fix crash when hiding parent
It's possible for itemChange to be called during destruction when deleting the QQuickShaderEffectImpl. We nullify m_impl before deleting it via another pointer to it, so we must check that it's not null before trying to use it. Fixes: QTBUG-86402 Change-Id: If4955445f7cc0d1f376bc9b86b95e1cca4d88ede Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io> (cherry picked from commit 266cd7638d887b31d56964a0f13fe208821703b1) Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--src/quick/items/qquickshadereffect.cpp6
-rw-r--r--tests/auto/quick/qquickshadereffect/data/hideParent.qml133
-rw-r--r--tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp14
3 files changed, 152 insertions, 1 deletions
diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp
index b3c8386fd9..8db4e7dc9e 100644
--- a/src/quick/items/qquickshadereffect.cpp
+++ b/src/quick/items/qquickshadereffect.cpp
@@ -868,7 +868,11 @@ void QQuickShaderEffect::itemChange(ItemChange change, const ItemChangeData &val
return;
}
#endif
- m_impl->handleItemChange(change, value);
+ // It's possible for itemChange to be called during destruction when deleting
+ // the QQuickShaderEffectImpl. We nullify m_impl before deleting it via another pointer
+ // to it, so we must check that it's not null before trying to use it here.
+ if (m_impl)
+ m_impl->handleItemChange(change, value);
QQuickItem::itemChange(change, value);
}
diff --git a/tests/auto/quick/qquickshadereffect/data/hideParent.qml b/tests/auto/quick/qquickshadereffect/data/hideParent.qml
new file mode 100644
index 0000000000..aeeb5b5f78
--- /dev/null
+++ b/tests/auto/quick/qquickshadereffect/data/hideParent.qml
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ id: root
+ width: 640
+ height: 480
+ objectName: "qtbug86402Container"
+
+ property bool finished
+
+ Item {
+ id: popup
+ objectName: "popup"
+ width: 200
+ height: 200
+
+ Rectangle {
+ id: rect
+ objectName: "rect"
+ implicitWidth: 100
+ implicitHeight: 100
+ color: "blue"
+
+ Item {
+ id: ripple
+ objectName: "ripple"
+ anchors.fill: parent
+ visible: false
+
+ Rectangle {
+ id: rippleBox
+ objectName: "rippleBox"
+ property real cx
+ property real cy
+ x: cx - width / 2
+ y: cy - height / 2
+ width: 0
+ height: width
+ radius: width / 2
+ color: Qt.darker("red", 1.8)
+ }
+ layer.effect: ShaderEffect {
+ id: mask
+ objectName: "shaderEffect"
+ property variant source
+ property variant mask: rect
+
+ fragmentShader: "
+ uniform lowp sampler2D source;
+ uniform lowp sampler2D mask;
+ varying highp vec2 qt_TexCoord0;
+ void main() {
+ gl_FragColor = texture2D(source, qt_TexCoord0) * texture2D(mask, qt_TexCoord0).a;
+ }"
+ }
+ }
+
+ SequentialAnimation {
+ id: rippleStartAnimation
+ running: popup.visible
+ onFinished: {
+ popup.parent = null
+ rippleEndAnimation.start()
+ }
+
+ ScriptAction {
+ script: {
+ rippleBox.width = 0
+ rippleBox.opacity = 0.3
+ ripple.visible = true
+ ripple.layer.enabled = true
+ }
+ }
+ NumberAnimation {
+ target: rippleBox
+ property: "width"
+ from: 0
+ to: Math.max(rect.width,
+ rect.height) * 2.2
+ duration: 100
+ }
+ }
+ SequentialAnimation {
+ id: rippleEndAnimation
+
+ onFinished: root.finished = true
+
+ //Causes Crash on QT Versions > 5.12.5
+ NumberAnimation {
+ target: rippleBox
+ property: "opacity"
+ to: 0
+ duration: 100
+ }
+ ScriptAction {
+ script: {
+ rippleBox.opacity = 0
+ ripple.layer.enabled = false
+ ripple.visible = false
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
index a57b7d4c1f..6537a64889 100644
--- a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
+++ b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
@@ -85,6 +85,8 @@ private slots:
void withoutQmlEngine();
+ void hideParent();
+
private:
enum PresenceFlags {
VertexPresent = 0x01,
@@ -336,6 +338,18 @@ void tst_qquickshadereffect::withoutQmlEngine()
delete window;
}
+// QTBUG-86402: hiding the parent of an item that uses an effect should not cause a crash.
+void tst_qquickshadereffect::hideParent()
+{
+ QScopedPointer<QQuickView> view(new QQuickView);
+ view->setSource(testFileUrl("hideParent.qml"));
+ QCOMPARE(view->status(), QQuickView::Ready);
+ view->show();
+ QVERIFY(QTest::qWaitForWindowExposed(view.data()));
+ // Should finish without crashing.
+ QTRY_VERIFY(view->rootObject()->property("finished").toBool());
+}
+
QTEST_MAIN(tst_qquickshadereffect)
#include "tst_qquickshadereffect.moc"