Skip to content

Commit

Permalink
Add Instance::unregisterSurface() in the destroy funct of the create …
Browse files Browse the repository at this point in the history
…surface

... method of the `struct wl_compositor_interface`

This commits prevents crashes by accessing to already deleted Surfaces
destroyed by a premature wl_client_destroy method call. For example,
trying to load a non-allowed URI filtered by a Content-Filter policy.

Changes:

* The Instance class implements an Instance::unregisterSurface().

* The destroy callback in the wl_resource_set_implementation for the
  created Surface now includes a Instance::unregisterSurface(). For this
  removes the surface from the ViewBackendMap avoiding dispatch operations
  over a already destroyed Surface.

* The Instance::dispatchFrameCallbacks(uint32_t bridgeId) still checks if the
  bridgeId has an associated Surface in the ViewBackendMap but now just
  logs a warning message and avoids to fail when associated element is not
  found. Instead of that the logic now just skips the dispatchFrameCallbacks
  if the surface is there.

Co-authored-by: Adrian Perez de Castro <aperez@igalia.com>
Acked-by: Adrian Perez de Castro <aperez@igalia.com>
Signed-off-by: Pablo Saavedra <psaavedra@igalia.com>
  • Loading branch information
psaavedra and aperezdc committed Apr 30, 2021
1 parent fcda2f7 commit 23117c3
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 4 deletions.
22 changes: 18 additions & 4 deletions src/ws.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "wpe-audio-server-protocol.h"
#include "wpe-bridge-server-protocol.h"
#include "wpe-video-plane-display-dmabuf-server-protocol.h"
#include <algorithm>
#include <cassert>
#include <sys/socket.h>
#include <unistd.h>
Expand Down Expand Up @@ -153,6 +154,7 @@ static const struct wl_compositor_interface s_compositorInterface = {
[](struct wl_resource* resource)
{
auto* surface = static_cast<Surface*>(wl_resource_get_user_data(resource));
WS::Instance::singleton().unregisterSurface(surface);
delete surface;
});
},
Expand Down Expand Up @@ -537,15 +539,27 @@ void Instance::unregisterViewBackend(uint32_t bridgeId)
}
}

void Instance::unregisterSurface(Surface* surface)
{
auto it = std::find_if(m_viewBackendMap.begin(), m_viewBackendMap.end(),
[surface](const std::pair<uint32_t, Surface*>& value) -> bool {
return value.second == surface;
});
if (it != m_viewBackendMap.end())
m_viewBackendMap.erase(it);
}

void Instance::dispatchFrameCallbacks(uint32_t bridgeId)
{
auto it = m_viewBackendMap.find(bridgeId);
if (it == m_viewBackendMap.end()) {
g_error("Instance::dispatchFrameCallbacks(): "
"Cannot find surface with bridgeId %" PRIu32 " in view backend map.", bridgeId);
g_warning("Instance::dispatchFrameCallbacks(): "
"Cannot find surface with bridgeId %" PRIu32 " in view "
"backend map. Probably the associated surface is gone "
"due to a premature exit in the client side", bridgeId);
} else {
it->second->dispatchFrameCallbacks();
}

it->second->dispatchFrameCallbacks();
}

} // namespace WS
1 change: 1 addition & 0 deletions src/ws.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ class Instance {
int createClient();

void registerSurface(uint32_t, Surface*);
void unregisterSurface(Surface*);
void registerViewBackend(uint32_t, APIClient&);
void unregisterViewBackend(uint32_t);
void dispatchFrameCallbacks(uint32_t);
Expand Down

0 comments on commit 23117c3

Please sign in to comment.