Skip to content

Commit 12d672e

Browse files
authored
Merge pull request #53 from wmww/fix-invalid-arg
Do not forward requests to libwayland if they include client-facing objects
2 parents 3eaeaac + 15d6aa6 commit 12d672e

4 files changed

Lines changed: 89 additions & 17 deletions

File tree

src/layer-surface.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -549,15 +549,18 @@ gint find_layer_surface_with_wl_surface (gconstpointer layer_surface, gconstpoin
549549
return wl_surface == needle ? 0 : 1;
550550
}
551551

552-
struct wl_proxy *
552+
gboolean
553553
layer_surface_handle_request (
554554
struct wl_proxy *proxy,
555555
uint32_t opcode,
556556
const struct wl_interface *interface,
557557
uint32_t version,
558558
uint32_t flags,
559-
union wl_argument *args)
559+
union wl_argument *args,
560+
struct wl_proxy **ret_proxy)
560561
{
562+
(void)interface;
563+
(void)flags;
561564
const char* type = proxy->object.interface->name;
562565
if (strcmp(type, xdg_wm_base_interface.name) == 0) {
563566
if (opcode == XDG_WM_BASE_GET_XDG_SURFACE) {
@@ -574,7 +577,8 @@ layer_surface_handle_request (
574577
self);
575578
self->client_facing_xdg_surface = (struct xdg_surface *)xdg_surface;
576579
layer_surface_create_surface_object(self, wl_surface);
577-
return xdg_surface;
580+
*ret_proxy = xdg_surface;
581+
return TRUE;
578582
}
579583
}
580584
} else if (strcmp(type, xdg_surface_interface.name) == 0) {
@@ -587,13 +591,15 @@ layer_surface_handle_request (
587591
NULL,
588592
(struct xdg_positioner *)args[2].o);
589593
zwlr_layer_surface_v1_get_popup (self->layer_surface, xdg_popup);
590-
return (struct wl_proxy *)xdg_popup;
594+
*ret_proxy = (struct wl_proxy *)xdg_popup;
595+
return TRUE;
591596
} else {
592597
g_critical ("tried to create popup before layer shell surface");
593-
return libwayland_shim_create_client_proxy (proxy, &xdg_popup_interface, version, NULL, NULL, NULL);
598+
*ret_proxy = libwayland_shim_create_client_proxy (proxy, &xdg_popup_interface, version, NULL, NULL, NULL);
599+
return TRUE;
594600
}
595601
}
596602
}
597603
}
598-
return libwayland_shim_real_wl_proxy_marshal_array_flags (proxy, opcode, interface, version, flags, args);
604+
return FALSE;
599605
}

src/layer-surface.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,13 @@ void layer_surface_set_keyboard_mode (LayerSurface *self, GtkLayerShellKeyboardM
6262
const char* layer_surface_get_namespace (LayerSurface *self);
6363

6464
// Used by libwayland wrappers
65-
struct wl_proxy *layer_surface_handle_request (
65+
gboolean layer_surface_handle_request (
6666
struct wl_proxy *proxy,
6767
uint32_t opcode,
6868
const struct wl_interface *interface,
6969
uint32_t version,
7070
uint32_t flags,
71-
union wl_argument *args);
71+
union wl_argument *args,
72+
struct wl_proxy **ret_proxy);
7273

7374
#endif // LAYER_SHELL_SURFACE_H

src/libwayland-shim.c

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,58 @@ libwayland_shim_get_client_proxy_data (struct wl_proxy *proxy, void* expected_ha
190190
}
191191
}
192192

193+
// Returns true if any arguments are proxies created by us (not known to libwayland)
194+
gboolean
195+
args_contains_client_facing_proxy (
196+
struct wl_proxy *proxy,
197+
uint32_t opcode,
198+
const struct wl_interface *interface,
199+
union wl_argument *args)
200+
{
201+
(void)interface;
202+
const char *sig_iter = proxy->object.interface->methods[opcode].signature;
203+
int i = 0;
204+
while (true) {
205+
struct argument_details arg;
206+
sig_iter = get_next_argument(sig_iter, &arg);
207+
switch (arg.type) {
208+
case 'o':
209+
if (args[i].o && args[i].o->id == client_facing_proxy_id) {
210+
return TRUE;
211+
}
212+
break;
213+
214+
case '\0':
215+
return FALSE;
216+
}
217+
i++;
218+
}
219+
}
220+
221+
// Returns the interface of the proxy object that this request is supposed to create, or NULL if none
222+
const struct wl_interface*
223+
get_interface_of_object_created_by_request (
224+
struct wl_proxy *proxy,
225+
uint32_t opcode,
226+
const struct wl_interface *interface)
227+
{
228+
const char *sig_iter = proxy->object.interface->methods[opcode].signature;
229+
int i = 0;
230+
while (true) {
231+
struct argument_details arg;
232+
sig_iter = get_next_argument(sig_iter, &arg);
233+
switch (arg.type) {
234+
case 'n':
235+
g_assert(interface[i].name);
236+
return interface + i;
237+
238+
case '\0':
239+
return NULL;
240+
}
241+
i++;
242+
}
243+
}
244+
193245
// Overrides the function in wayland-client.c in libwayland
194246
void
195247
wl_proxy_destroy (struct wl_proxy *proxy)
@@ -221,6 +273,8 @@ wl_proxy_marshal_array_flags (
221273
{
222274
libwayland_shim_init ();
223275
if (proxy->object.id == client_facing_proxy_id) {
276+
// libwayland doesn't know about the object this request is on. It must not find out about this object. If it
277+
// finds out it will be very upset.
224278
struct wrapped_proxy *wrapper = (struct wrapped_proxy *)proxy;
225279
struct wl_proxy *result = NULL;
226280
if (wrapper->handler)
@@ -229,7 +283,26 @@ wl_proxy_marshal_array_flags (
229283
wl_proxy_destroy(proxy);
230284
return result;
231285
} else {
232-
return layer_surface_handle_request (proxy, opcode, interface, version, flags, args);
286+
struct wl_proxy *ret_proxy = NULL;
287+
if (layer_surface_handle_request (proxy, opcode, interface, version, flags, args, &ret_proxy)) {
288+
// The behavior of the request has been overridden
289+
return ret_proxy;
290+
} else if (args_contains_client_facing_proxy (proxy, opcode, interface, args)) {
291+
// We can't do the normal thing because one of the arguments is an object libwayand doesn't know about, but
292+
// no override behavior was taken. Hopefully we can safely ignore this request.
293+
const struct wl_interface *created = get_interface_of_object_created_by_request(proxy, opcode, interface);
294+
if (created) {
295+
// We need to create a stub object to make the client happy, it will ignore all requests and represents
296+
// nothing in libwayland/the server
297+
return libwayland_shim_create_client_proxy (proxy, created, created->version, NULL, NULL, NULL);
298+
} else {
299+
// Ignore the request
300+
return NULL;
301+
}
302+
} else {
303+
// Forward the request on to libwayland without modification, this is the most common path
304+
return libwayland_shim_real_wl_proxy_marshal_array_flags (proxy, opcode, interface, version, flags, args);
305+
}
233306
}
234307
}
235308

src/libwayland-shim.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,4 @@ void libwayland_shim_clear_client_proxy_data (struct wl_proxy *proxy);
5757

5858
void *libwayland_shim_get_client_proxy_data (struct wl_proxy *proxy, void* expected_handler);
5959

60-
extern struct wl_proxy * (*libwayland_shim_real_wl_proxy_marshal_array_flags) (
61-
struct wl_proxy *proxy,
62-
uint32_t opcode,
63-
const struct wl_interface *interface,
64-
uint32_t version,
65-
uint32_t flags,
66-
union wl_argument *args);
67-
6860
#endif // LIBWAYLAND_SHIM_H

0 commit comments

Comments
 (0)