aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickshadereffect.cpp
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@jollamobile.com>2014-02-19 21:38:17 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-02-20 23:08:01 +0100
commitf158fa7feaa5d9fc2ae17aa16853acbbb947443a (patch)
treefb78a51d5310786f4531cf9127721bb2b772f90d /src/quick/items/qquickshadereffect.cpp
parent43f983350a548b1b663ea07a0e87e4cc58834214 (diff)
Prevent dangling pointer in QQuickShaderEffectSource.
Task-number: QTBUG-36931 Change-Id: Idb584a8703a8d93d2cbcd3feb7942476dc165a59 Reviewed-by: Mitch Curtis <mitch.curtis@digia.com> Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/quick/items/qquickshadereffect.cpp')
-rw-r--r--src/quick/items/qquickshadereffect.cpp21
1 files changed, 20 insertions, 1 deletions
diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp
index 9a20703f18..e57b7abddc 100644
--- a/src/quick/items/qquickshadereffect.cpp
+++ b/src/quick/items/qquickshadereffect.cpp
@@ -478,6 +478,19 @@ void QQuickShaderEffectCommon::sourceDestroyed(QObject *object)
}
}
+static bool qquick_uniqueInUniformData(QQuickItem *source, const QVector<QQuickShaderEffectMaterial::UniformData> *uniformData, int typeToSkip, int indexToSkip)
+{
+ for (int s=0; s<QQuickShaderEffectMaterialKey::ShaderTypeCount; ++s) {
+ for (int i=0; i<uniformData[s].size(); ++i) {
+ if (s == typeToSkip && i == indexToSkip)
+ continue;
+ const QQuickShaderEffectMaterial::UniformData &d = uniformData[s][i];
+ if (d.specialType == QQuickShaderEffectMaterial::UniformData::Sampler && qvariant_cast<QObject *>(d.value) == source)
+ return false;
+ }
+ }
+ return true;
+}
void QQuickShaderEffectCommon::propertyChanged(QQuickItem *item, int mappedId,
bool *textureProviderChanged)
@@ -490,7 +503,13 @@ void QQuickShaderEffectCommon::propertyChanged(QQuickItem *item, int mappedId,
if (source) {
if (item->window())
QQuickItemPrivate::get(source)->derefWindow();
- QObject::disconnect(source, SIGNAL(destroyed(QObject*)), item, SLOT(sourceDestroyed(QObject*)));
+
+ // QObject::disconnect() will disconnect all matching connections. If the same
+ // source has been attached to two separate samplers, then changing one of them
+ // would trigger both to be disconnected. Without the connection we'll end up
+ // with a dangling pointer in the uniformData.
+ if (qquick_uniqueInUniformData(source, uniformData, shaderType, index))
+ QObject::disconnect(source, SIGNAL(destroyed(QObject*)), item, SLOT(sourceDestroyed(QObject*)));
}
d.value = item->property(d.name.constData());