1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2From: Lloyd Pique <[email protected]> 3Date: Fri, 11 Mar 2022 18:17:20 -0800 4Subject: [PATCH 4/6] client: Safe cast a "wl_object *" to "wl_proxy *" 5 6Client message observers 4/6 7 8When given an array of wl_arguments for a wl_closure, the ".o" field is an 9opaque wl_object pointer, which the client code cannot really do anything with, 10without a potentially unsafe cast that assumes details about the internal 11implementation. 12 13By adding a wl_proxy_from_object() function to the client interface, the client 14can safely get the wl_proxy pointer. 15 16This can be used by client message observers in particular to get the proxy id 17and class name, for logging those details. 18 19Signed-off-by: Lloyd Pique <[email protected]> 20 21diff --git a/src/wayland-client-core.h b/src/wayland-client-core.h 22index 2aa72a4..a57cbe0 100644 23--- a/src/wayland-client-core.h 24+++ b/src/wayland-client-core.h 25@@ -222,6 +222,9 @@ wl_proxy_get_class(struct wl_proxy *proxy); 26 void 27 wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue); 28 29+struct wl_proxy * 30+wl_proxy_from_object(struct wl_object *object); 31+ 32 struct wl_display * 33 wl_display_connect(const char *name); 34 35diff --git a/src/wayland-client.c b/src/wayland-client.c 36index 04b4f60..ab68bdb 100644 37--- a/src/wayland-client.c 38+++ b/src/wayland-client.c 39@@ -2594,6 +2594,28 @@ wl_proxy_wrapper_destroy(void *proxy_wrapper) 40 free(wrapper); 41 } 42 43+/** Safely converts an object into its corresponding proxy 44+ * 45+ * \param object object to get the proxy for 46+ * \return A corresponding proxy, or NULL on failure. 47+ * 48+ * Safely converts an object into its corresponding proxy. 49+ * 50+ * This is useful for implementing functions that are given a \c wl_argument 51+ * array, and that need to do further introspection on the ".o" field, as it 52+ * is otherwise an opaque type. 53+ * 54+ * \memberof wl_proxy 55+ */ 56+WL_EXPORT struct wl_proxy * 57+wl_proxy_from_object(struct wl_object *object) 58+{ 59+ struct wl_proxy *proxy; 60+ if (object == NULL) 61+ return NULL; 62+ return wl_container_of(object, proxy, object); 63+} 64+ 65 WL_EXPORT void 66 wl_log_set_handler_client(wl_log_func_t handler) 67 { 68diff --git a/tests/protocol-logger-test.c b/tests/protocol-logger-test.c 69index 082f055..9420b5e 100644 70--- a/tests/protocol-logger-test.c 71+++ b/tests/protocol-logger-test.c 72@@ -275,10 +275,11 @@ client_log_to_stderr_demo(void *user_data, enum wl_client_message_type type, 73 break; 74 case 'o': 75 if (args[i].o) { 76- // Note: server logger should instead cast to 77- // wl_resource, and use wl_resource_get_class 78- // and wl_resource_get_id. 79- arg_proxy = (struct wl_proxy *)(args[i].o); 80+ // Note: server logger should instead use 81+ // wl_resource_from_object, and then 82+ // wl_resource_get_class and 83+ // wl_resource_get_id. 84+ arg_proxy = wl_proxy_from_object(args[i].o); 85 arg_class = wl_proxy_get_class(arg_proxy); 86 87 fprintf(f, "%s@%u", 88