client: Safe cast a "wl_object *" to "wl_proxy *"

Client message observers 4/6

When given an array of wl_arguments for a wl_closure, the ".o" field is an
opaque wl_object pointer, which the client code cannot really do anything with,
without a potentially unsafe cast that assumes details about the internal
implementation.

By adding a wl_proxy_from_object() function to the client interface, the client
can safely get the wl_proxy pointer.

This can be used by client message observers in particular to get the proxy id
and class name, for logging those details.

Signed-off-by: Lloyd Pique <lpique@google.com>
This commit is contained in:
Lloyd Pique 2022-03-11 18:17:20 -08:00
parent 3df74daed4
commit e5e7cc57fa
3 changed files with 30 additions and 4 deletions

View file

@ -228,6 +228,9 @@ wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue);
struct wl_event_queue *
wl_proxy_get_queue(const struct wl_proxy *proxy);
struct wl_proxy *
wl_proxy_from_object(struct wl_object *object);
const char *
wl_event_queue_get_name(const struct wl_event_queue *queue);

View file

@ -2720,6 +2720,28 @@ wl_proxy_wrapper_destroy(void *proxy_wrapper)
free(wrapper);
}
/** Safely converts an object into its corresponding proxy
*
* \param object object to get the proxy for
* \return A corresponding proxy, or NULL on failure.
*
* Safely converts an object into its corresponding proxy.
*
* This is useful for implementing functions that are given a \c wl_argument
* array, and that need to do further introspection on the ".o" field, as it
* is otherwise an opaque type.
*
* \memberof wl_proxy
*/
WL_EXPORT struct wl_proxy *
wl_proxy_from_object(struct wl_object *object)
{
struct wl_proxy *proxy;
if (object == NULL)
return NULL;
return wl_container_of(object, proxy, object);
}
WL_EXPORT void
wl_log_set_handler_client(wl_log_func_t handler)
{

View file

@ -294,10 +294,11 @@ client_log_to_stderr_demo(void *user_data, enum wl_client_message_type type,
break;
case 'o':
if (args[i].o) {
// Note: server logger should instead cast to
// wl_resource, and use wl_resource_get_class
// and wl_resource_get_id.
arg_proxy = (struct wl_proxy *)(args[i].o);
// Note: server logger should instead use
// wl_resource_from_object, and then
// wl_resource_get_class and
// wl_resource_get_id.
arg_proxy = wl_proxy_from_object(args[i].o);
arg_class = wl_proxy_get_class(arg_proxy);
fprintf(f, "%s#%u",