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

Summary:
Destroying the BlurInterface 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 BlurInterface it could result in heap-use-after-free.

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

Reviewers: #plasma

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D1708
This commit is contained in:
Martin Gräßlin 2016-05-30 09:53:53 +02:00
parent 08bc189f8d
commit 3f1db0cfde
2 changed files with 34 additions and 8 deletions

View file

@ -44,6 +44,7 @@ private Q_SLOTS:
void cleanup();
void testCreate();
void testSurfaceDestroy();
private:
KWayland::Server::Display *m_display;
@ -177,5 +178,38 @@ void TestBlur::testCreate()
QVERIFY(destroyedSpy.wait());
}
void TestBlur::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 blurChanged(serverSurface, &KWayland::Server::SurfaceInterface::blurChanged);
QVERIFY(blurChanged.isValid());
QScopedPointer<KWayland::Client::Blur> blur(m_blurManager->createBlur(surface.data()));
blur->setRegion(m_compositor->createRegion(QRegion(0, 0, 10, 20), nullptr));
blur->commit();
surface->commit(KWayland::Client::Surface::CommitFlag::None);
QVERIFY(blurChanged.wait());
QCOMPARE(serverSurface->blur()->region(), QRegion(0, 0, 10, 20));
// destroy the parent surface
QSignalSpy surfaceDestroyedSpy(serverSurface, &QObject::destroyed);
QVERIFY(surfaceDestroyedSpy.isValid());
QSignalSpy blurDestroyedSpy(serverSurface->blur(), &QObject::destroyed);
QVERIFY(blurDestroyedSpy.isValid());
surface.reset();
QVERIFY(surfaceDestroyedSpy.wait());
QVERIFY(blurDestroyedSpy.isEmpty());
// destroy the blur
blur.reset();
QVERIFY(blurDestroyedSpy.wait());
}
QTEST_GUILESS_MAIN(TestBlur)
#include "test_wayland_blur.moc"

View file

@ -106,14 +106,6 @@ void BlurManagerInterface::Private::createBlur(wl_client *client, wl_resource *r
delete blur;
return;
}
QObject::connect(s, &QObject::destroyed, blur,
[blur] {
if (blur->resource()) {
wl_resource_destroy(blur->resource());
delete blur;
}
}
);
s->d_func()->setBlur(QPointer<BlurInterface>(blur));
}