[PATCH wayland 2/5] server: set map entry to NULL after resource is destroyed

Pekka Paalanen ppaalanen at gmail.com
Mon May 16 08:42:05 UTC 2016


On Fri, 13 May 2016 15:01:19 +0200
Marek Chalupa <mchqwerty at gmail.com> wrote:

> We did it only for client entries for some reason, so when
> we used wl_client_get_object() for some server object that
> has been destroyed, we got dangling pointer.
> 
> NOTE: this is basically an API change, since it changes
> the return value of wl_client_get_object() in some corner cases.
> However, now we return NULL insted of a pointer to invalid memory,
> which could be OK API break.

Hi Marek,

I'm not sure I see why there is something to fix here.

Let's assume we gave a server-side created wl_resource, and
wl_resource_destroy() is called on it:

wl_resource_destroy():
- destroy_resource():
- - does nothing to the map, really
- server-side created object so get to else-branch of
  (id < WL_SERVER_ID_START)
- wl_map_remove():
- - The entry is completely removed from the map, so wl_map_lookup() on
    it will return NULL.
- At this point the id longer exists and can be re-used, so no lookups
  should be made on it.

Then if we look at wl_client_get_object():
- wl_map_lookup()
Ok, so this will just return NULL now, but assuming the id has not been
re-used. If it was re-used, it returns a valid pointer to a "wrong"
object.

Did I miss something?

To me it seems there are two things that make the premise of this patch
invalid:
1. You already get NULL from wl_client_lookup_object().
2. The lookup would be invalid anyway as the id as you knew it does not
   exist anymore.


The other call site for destroy_resource() is wl_client_destroy() which
also means all ids are invalidated.

Now, client entries are NULLed, because they *need* to stay in the map,
because a) the free_list is only for the map->side of the two object
arrays in a wl_map, and b) wl_map_insert_at() will only increase the
array size by one at most. The latter is also limiting what ids clients
can allocate at a time.

Therefore, NAK for this patch because the premise why this patch was
written is false.

If you wanted to apply this only as a clean-up or clarification, I'm
not sure it would be a win. wl_map_remove() would still be called only
for server-allocated ids.


Thanks,
pq

> Signed-off-by: Marek Chalupa <mchqwerty at gmail.com>
> ---
>  src/wayland-server.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/src/wayland-server.c b/src/wayland-server.c
> index f745e62..c93a426 100644
> --- a/src/wayland-server.c
> +++ b/src/wayland-server.c
> @@ -562,16 +562,20 @@ destroy_resource(void *element, void *data)
>  {
>  	struct wl_resource *resource = element;
>  	struct wl_client *client = resource->client;
> +	uint32_t id = resource->object.id;
>  	uint32_t flags;
>  
>  	wl_signal_emit(&resource->destroy_signal, resource);
>  
> -	flags = wl_map_lookup_flags(&client->objects, resource->object.id);
> +	flags = wl_map_lookup_flags(&client->objects, id);
>  	if (resource->destroy)
>  		resource->destroy(resource);
>  
>  	if (!(flags & WL_MAP_ENTRY_LEGACY))
>  		free(resource);
> +
> +	/* replace the object with NULL since it is destroyed */
> +	wl_map_insert_at(&client->objects, 0, id, NULL);
>  }
>  
>  WL_EXPORT void
> @@ -584,11 +588,9 @@ wl_resource_destroy(struct wl_resource *resource)
>  	destroy_resource(resource, NULL);
>  
>  	if (id < WL_SERVER_ID_START) {
> -		if (client->display_resource) {
> +		if (client->display_resource)
>  			wl_resource_queue_event(client->display_resource,
>  						WL_DISPLAY_DELETE_ID, id);
> -		}
> -		wl_map_insert_at(&client->objects, 0, id, NULL);
>  	} else {
>  		wl_map_remove(&client->objects, id);
>  	}

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 811 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/wayland-devel/attachments/20160516/4d8aebb1/attachment-0001.sig>


More information about the wayland-devel mailing list