Commit 9558edb9 authored by Martin Flöser's avatar Martin Flöser
Browse files

[server] Fix possible crash after deleting an output(device)interface

After deleting an OutputInterface the resources are not necessarily
destroyed, so unbind might still be called. The existing code just
casted the resource's user data which could then point to invalidated
memory.

This change verifies that we still have a Private* for the resource.
If not, it doesn't have to do any cleanup anyway.

REVIEW: 126097
parent a28b9ee1
......@@ -61,6 +61,7 @@ public:
static OutputInterface *get(wl_resource *native);
private:
static Private *cast(wl_resource *native);
static void unbind(wl_resource *resource);
void bind(wl_client *client, uint32_t version, uint32_t id) override;
int32_t toTransform() const;
......@@ -89,12 +90,20 @@ OutputInterface::Private::~Private()
}
OutputInterface *OutputInterface::Private::get(wl_resource *native)
{
if (Private *p = cast(native)) {
return p->q;
}
return nullptr;
}
OutputInterface::Private *OutputInterface::Private::cast(wl_resource *native)
{
for (auto it = s_privates.constBegin(); it != s_privates.constEnd(); ++it) {
const auto &resources = (*it)->resources;
auto rit = std::find_if(resources.begin(), resources.end(), [native] (const ResourceData &data) { return data.resource == native; });
if (rit != resources.end()) {
return (*it)->q;
return (*it);
}
}
return nullptr;
......@@ -324,7 +333,10 @@ void OutputInterface::Private::bind(wl_client *client, uint32_t version, uint32_
void OutputInterface::Private::unbind(wl_resource *resource)
{
auto o = reinterpret_cast<OutputInterface::Private*>(wl_resource_get_user_data(resource));
Private *o = cast(resource);
if (!o) {
return;
}
auto it = std::find_if(o->resources.begin(), o->resources.end(), [resource](const ResourceData &r) { return r.resource == resource; });
if (it != o->resources.end()) {
o->resources.erase(it);
......
......@@ -67,6 +67,7 @@ public:
static OutputDeviceInterface *get(wl_resource *native);
private:
static Private *cast(wl_resource *native);
static void unbind(wl_resource *resource);
void bind(wl_client *client, uint32_t version, uint32_t id) override;
int32_t toTransform() const;
......@@ -96,12 +97,20 @@ OutputDeviceInterface::Private::~Private()
}
OutputDeviceInterface *OutputDeviceInterface::Private::get(wl_resource *native)
{
if (Private *p = cast(native)) {
return p->q;
}
return nullptr;
}
OutputDeviceInterface::Private *OutputDeviceInterface::Private::cast(wl_resource *native)
{
for (auto it = s_privates.constBegin(); it != s_privates.constEnd(); ++it) {
const auto &resources = (*it)->resources;
auto rit = std::find_if(resources.begin(), resources.end(), [native] (const ResourceData &data) { return data.resource == native; });
if (rit != resources.end()) {
return (*it)->q;
return (*it);
}
}
return nullptr;
......@@ -350,7 +359,10 @@ void OutputDeviceInterface::Private::bind(wl_client *client, uint32_t version, u
void OutputDeviceInterface::Private::unbind(wl_resource *resource)
{
auto o = reinterpret_cast<OutputDeviceInterface::Private*>(wl_resource_get_user_data(resource));
Private *o = cast(resource);
if (!o) {
return;
}
auto it = std::find_if(o->resources.begin(), o->resources.end(), [resource](const ResourceData &r) { return r.resource == resource; });
if (it != o->resources.end()) {
o->resources.erase(it);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment