[server] Don't destroy ContrastInterface when parent SurfaceInterface is destroyed

Summary:
Destroying the ContrastInterface on the server side before the client has
a chance to cleanup results in a protocol error:
wl_display@1: error 0: invalid object 7

Which would terminate the client. If we would not destroy the resource,
but only delete the ContrastInterface it could result in
heap-use-after-free.

So just don't do anything, the client needs to cleanup which will result
in the ContrastInterface being deleted.

Reviewers: #plasma

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D1709
This commit is contained in:
Martin Gräßlin 2016-05-30 10:24:27 +02:00
parent 3f1db0cfde
commit 5232dc5f0f
2 changed files with 34 additions and 8 deletions

View file

@ -47,6 +47,7 @@ private Q_SLOTS:
void cleanup();
void testCreate();
void testSurfaceDestroy();
private:
KWayland::Server::Display *m_display;
@ -187,5 +188,38 @@ void TestContrast::testCreate()
QVERIFY(destroyedSpy.wait());
}
void TestContrast::testSurfaceDestroy()
{
QSignalSpy serverSurfaceCreated(m_compositorInterface, &KWayland::Server::CompositorInterface::surfaceCreated);
QVERIFY(serverSurfaceCreated.isValid());
QScopedPointer<KWayland::Client::Surface> surface(m_compositor->createSurface());
QVERIFY(serverSurfaceCreated.wait());
auto serverSurface = serverSurfaceCreated.first().first().value<KWayland::Server::SurfaceInterface*>();
QSignalSpy contrastChanged(serverSurface, &KWayland::Server::SurfaceInterface::contrastChanged);
QVERIFY(contrastChanged.isValid());
QScopedPointer<KWayland::Client::Contrast> contrast(m_contrastManager->createContrast(surface.data()));
contrast->setRegion(m_compositor->createRegion(QRegion(0, 0, 10, 20), nullptr));
contrast->commit();
surface->commit(KWayland::Client::Surface::CommitFlag::None);
QVERIFY(contrastChanged.wait());
QCOMPARE(serverSurface->contrast()->region(), QRegion(0, 0, 10, 20));
// destroy the parent surface
QSignalSpy surfaceDestroyedSpy(serverSurface, &QObject::destroyed);
QVERIFY(surfaceDestroyedSpy.isValid());
QSignalSpy contrastDestroyedSpy(serverSurface->contrast(), &QObject::destroyed);
QVERIFY(contrastDestroyedSpy.isValid());
surface.reset();
QVERIFY(surfaceDestroyedSpy.wait());
QVERIFY(contrastDestroyedSpy.isEmpty());
// destroy the blur
contrast.reset();
QVERIFY(contrastDestroyedSpy.wait());
}
QTEST_GUILESS_MAIN(TestContrast)
#include "test_wayland_contrast.moc"

View file

@ -106,14 +106,6 @@ void ContrastManagerInterface::Private::createContrast(wl_client *client, wl_res
delete contrast;
return;
}
QObject::connect(s, &QObject::destroyed, contrast,
[contrast] {
if (contrast->resource()) {
wl_resource_destroy(contrast->resource());
delete contrast;
}
}
);
s->d_func()->setContrast(QPointer<ContrastInterface>(contrast));
}