From 0115aceb584b007a6faba3de701a972659025fd7 Mon Sep 17 00:00:00 2001 From: Jan D Date: Sat, 4 Apr 2015 16:10:06 +0200 Subject: [PATCH] Close a timing hole in selections. Fixes: debbugs:16737 * src/xselect.c (x_reply_selection_request) (receive_incremental_selection): Call set_property_change_object inside block_input. (wait_for_property_change): Move set property_change_reply(_object) outside of this function. (set_property_change_object): New function. --- src/ChangeLog | 9 +++++++++ src/xselect.c | 28 +++++++++++++++++++++++----- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 09225f26dfc..1c3f933d7d8 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2015-04-04 Jan Djärv + + * xselect.c (x_reply_selection_request) + (receive_incremental_selection): Call set_property_change_object + inside block_input. + (wait_for_property_change): Move set property_change_reply(_object) + outside of this function (Bug#16737). + (set_property_change_object): New function. + 2015-04-03 Jan Djärv * xterm.c (handle_one_xevent): Always redraw tool tips on diff --git a/src/xselect.c b/src/xselect.c index 027192dfea2..1570c4fef9c 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -531,6 +531,16 @@ static struct prop_location *property_change_reply_object; static struct prop_location *property_change_wait_list; +static void +set_property_change_object (struct prop_location *location) +{ + /* Input must be blocked so we don't get the event before we set these. */ + if (! input_blocked_p ()) + emacs_abort (); + XSETCAR (property_change_reply, Qnil); + property_change_reply_object = location; +} + /* Send the reply to a selection request event EVENT. */ @@ -633,6 +643,11 @@ x_reply_selection_request (struct input_event *event, { int format_bytes = cs->format / 8; bool had_errors_p = x_had_errors_p (display); + + /* Must set this inside block_input (). unblock_input may read + events and setting property_change_reply in + wait_for_property_change is then too late. */ + set_property_change_object (cs->wait_object); unblock_input (); bytes_remaining = cs->size; @@ -673,6 +688,8 @@ x_reply_selection_request (struct input_event *event, : format_bytes); XFlush (display); had_errors_p = x_had_errors_p (display); + // See comment above about property_change_reply. + set_property_change_object (cs->wait_object); unblock_input (); if (had_errors_p) break; @@ -1059,14 +1076,11 @@ wait_for_property_change (struct prop_location *location) { ptrdiff_t count = SPECPDL_INDEX (); - if (property_change_reply_object) - emacs_abort (); - /* Make sure to do unexpect_property_change if we quit or err. */ record_unwind_protect_ptr (wait_for_property_change_unwind, location); - XSETCAR (property_change_reply, Qnil); - property_change_reply_object = location; + /* See comment in x_reply_selection_request about setting + property_change_reply. Do not do it here. */ /* If the event we are waiting for arrives beyond here, it will set property_change_reply, because property_change_reply_object says so. */ @@ -1381,6 +1395,8 @@ receive_incremental_selection (struct x_display_info *dpyinfo, wait_object = expect_property_change (display, window, property, PropertyNewValue); XFlush (display); + // See comment in x_reply_selection_request about property_change_reply. + set_property_change_object (wait_object); unblock_input (); while (true) @@ -1419,6 +1435,8 @@ receive_incremental_selection (struct x_display_info *dpyinfo, XDeleteProperty (display, window, property); wait_object = expect_property_change (display, window, property, PropertyNewValue); + // See comment in x_reply_selection_request about property_change_reply. + set_property_change_object (wait_object); XFlush (display); unblock_input (); -- 2.39.5