From 102d4975a1e9cecb7850f668dc44b52857bf66fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 31 Oct 2020 10:36:11 +0100 Subject: [PATCH] selection: dnd: fix wl_data_offer_destroy() race MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At the end of a drag-and-drop operation, we need to call `wl_data_offer_finish()`. We *must* ensure the data offer hasn’t been destroyed before that. This could previously happen if the compositor decided to send a regular clipboard offer *after* we had started a drop operation, but *before* it had finished. The dnd offer was then destroyed when the clipboard offer was received, causing us to crash in `wl_data_offer_finish()`. To handle this, let the receive_offer_context take over ownership of the data_offer pointer, and “manually” destroy it *after* calling `wl_data_offer_finish()` in `receive_dnd_done()`. Note: we should not, and can not, do the same thing for regular clipboard and primary selection offers; such offers can be used multiple times and should *not* be destroyed after a single copy operation. --- selection.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/selection.c b/selection.c index 6e0d8d5a..6767f5fe 100644 --- a/selection.c +++ b/selection.c @@ -1777,6 +1777,7 @@ receive_dnd_done(void *user) struct receive_offer_context *ctx = user; wl_data_offer_finish(ctx->data_offer); + wl_data_offer_destroy(ctx->data_offer); receive_offer_done(user); } @@ -1827,6 +1828,10 @@ drop(void *data, struct wl_data_device *wl_data_device) ? &receive_offer_uri : &receive_offer_text), &receive_dnd_done, ctx); + + /* data offer is now “owned” by the receive context */ + clipboard->data_offer = NULL; + clipboard->mime_type = DATA_OFFER_MIME_UNSET; } static void