Opened 5 years ago

Last modified 5 years ago

#16636 new defect

Clipboard not sufficiently protected from reentry

Reported by: martin.steghoefer Owned by:
Priority: normal Milestone:
Component: wxGTK Version: 3.0.1
Keywords: Cc: kinaouherve@…
Blocked By: Blocking:
Patch: no

Description

In the wxGTK implementation, some wxClipboard methods (e.g. IsSupported) have to process pending GDK events (via wxClipboardSync and YieldFor) in order to complete their task. However, during the processing of those events the handler code may call wxClipboard methods itself, causing reentry that throws an assertion failure. The wxClipboardSync and YieldFor code tries to work around this problem by overriding the gdk event handler and processing only those events that are relevant for the clipboard.

However, this protection has holes:

The first one is the categorization of events in the overriding event handler wxgtk_main_do_event. It classifies all events of the type GDK_PROPERTY_NOTIFY as potentially relevant for the clipboard. Unfortunately this includes the processing of the EVT_SHOW events. Prohibiting clipboard operations in the handling of this message would be a very strong restriction. The attached clipboard-show.cxx is able to reliably reproduce that behavior (WITHOUT the wxSleep call). The relevant code for that message filtering is in gtk/evtloop.cpp (line 295):

    case GDK_PROPERTY_NOTIFY:
        // This one is special: it can be used for UI purposes but also for
        // clipboard operations, so allow it in both cases (we probably could
        // examine the event itself to distinguish between the two cases but
        // this would be unnecessarily complicated).
        cat2 = wxEVT_CATEGORY_CLIPBOARD;
        // Fall through.

But even without that flaw, clipboard operations in the processing of EVT_SHOW events would be dangerous because of a second hole: The YieldFor method only changes the event handler (gdk_event_handler_set) before giving up the control by calling gtk_main_iteration, but doesn't take into account that gtk_main_iteration also processes timer events (g_timeout_dispatch). Via a workaround for broken window managers in wxWidgets (request_frame_extents_timeout in toplevel.cpp), this can again cause a call to the handler of EVT_SHOW events within the first clipboard operation. You can reproduce this behavior by executing the attached example clipboard-show.cxx WITH the wxSleep call.

This second hole doesn't only prevent you from clipboard operations in the processing of EVT_SHOW events, but also in the processing of timer events, like can be seen in the attached example clipboard-timer.cpp.

Find attached the C++ code for the mentioned examples and the relevant stacktraces for all mentioned execution cases.

Attachments (5)

clipboard-show.cxx download (2.1 KB) - added by martin.steghoefer 5 years ago.
First example; can reproduce both holes (by activating/deactivating the "wxSleep")
clipboard-timer.cxx download (1.5 KB) - added by martin.steghoefer 5 years ago.
Second example; can reproduce the second hole (timer)
stacktrace-show-msg-dispatch.txt download (2.7 KB) - added by martin.steghoefer 5 years ago.
Stacktrace for first example *without* wxSleep (first hole)
stacktrace-show-timeout.txt download (2.2 KB) - added by martin.steghoefer 5 years ago.
Stacktrace for first example *with* wxSleep (second hole, timer)
stacktrace-timer.txt download (1.9 KB) - added by martin.steghoefer 5 years ago.
Stacktrace for second example (second hole, timer)

Download all attachments as: .zip

Change History (7)

Changed 5 years ago by martin.steghoefer

First example; can reproduce both holes (by activating/deactivating the "wxSleep")

Changed 5 years ago by martin.steghoefer

Second example; can reproduce the second hole (timer)

Changed 5 years ago by martin.steghoefer

Stacktrace for first example *without* wxSleep (first hole)

Changed 5 years ago by martin.steghoefer

Stacktrace for first example *with* wxSleep (second hole, timer)

Changed 5 years ago by martin.steghoefer

Stacktrace for second example (second hole, timer)

comment:1 Changed 5 years ago by vadz

Ideal would be to yield only for the selection-received events, but I'm not sure how to do it.

Does anybody have any ideas?

comment:2 Changed 5 years ago by kinaou

  • Cc kinaouherve@… added
Note: See TracTickets for help on using tickets.