Tk Source Code

View Ticket
Login
2025-11-04
20:45 • Closed ticket [6da88540]: Aqua: avoid use-after-free during RefocusGrabWindow() plus 7 other changes artifact: 82641eee user: jan.nijtmans
20:42
Fix [6da885404a]: Aqua: avoid use-after-free during RefocusGrabWindow() check-in: dc200f18 user: jan.nijtmans tags: core-8-6-branch
2025-07-31
20:37 • Ticket [6da88540] Aqua: avoid use-after-free during RefocusGrabWindow() status still Open with 3 other changes artifact: 5f7873b1 user: chrstphrchvz
2025-07-30
16:36 • Ticket [6da88540]: 4 changes artifact: 23582849 user: marc_culler
2025-07-29
15:35
Fix [6da885404a]: Aqua: use-after-free during RefocusGrabWindow() leaf check-in: 6ea148e1 user: chrstphrchvz tags: bug-6da885404a
14:18 • Ticket [6da88540] Aqua: avoid use-after-free during RefocusGrabWindow() status still Open with 3 other changes artifact: 5971ac1d user: chrstphrchvz
2022-08-30
18:59 • New ticket [ab95811e] Aqua: prevent use-after-free crashes. artifact: c1ba02ad user: chrstphrchvz
2022-08-28
20:13 • Ticket [6da88540] Aqua: avoid use-after-free during RefocusGrabWindow() status still Open with 3 other changes artifact: 78a90c31 user: chrstphrchvz
20:11 • Add attachment 6da885404a6e.diff to ticket [6da88540] artifact: cfc307de user: chrstphrchvz
20:08 • New ticket [6da88540] Aqua: avoid use-after-free in RefocusGrabWindow(). artifact: d4b3ad8a user: chrstphrchvz

Ticket UUID: 6da885404a6e5efb0ba11f3948950e69687e916d
Title: Aqua: avoid use-after-free during RefocusGrabWindow()
Type: Patch Version: core-8-6-branch
Submitter: chrstphrchvz Created on: 2022-08-28 20:08:46
Subsystem: 56. [grab] Assigned To: jan.nijtmans
Priority: 5 Medium Severity: Important
Status: Closed Last Modified: 2025-11-04 20:45:06
Resolution: Fixed Closed By: jan.nijtmans
    Closed on: 2025-11-04 20:45:06
Description:

Using cgimage-drawing, I recently encountered a use-after-free crash when bgerror is invoked. I cannot always reproduce it with the steps I originally used, but I came up with a simpler script that reliably triggers the issue:

    toplevel .t
    grab .t
    after 2000 {bind .t <Activate> {destroy .t}}

Once the toplevel .t is created, switch to another app, wait 2 seconds, then switch back to Tk by clicking on toplevel .t. The grab window .t will be destroyed and freed before the RefocusGrabWindow() idle handler is called. Excerpt from Address Sanitizer (-DPURIFY -fsanitize=address) report:

==98370==ERROR: AddressSanitizer: heap-use-after-free on address 0x614000087b38 at pc 0x000100d829fb bp 0x7ffeefbfe8d0 sp 0x7ffeefbfe8c8
READ of size 4 at 0x614000087b38 thread T0
    #0 0x100d829fa in TkpChangeFocus tkMacOSXWm.c:6602
    #1 0x100d0dc91 in RefocusGrabWindow tkMacOSXWindowEvent.c:333
    #2 0x1024c1299 in TclServiceIdle tclTimer.c:751
    #3 0x102354593 in Tcl_DoOneEvent tclNotify.c:980
    #4 0x10023a0af in Tk_MainLoop tkEvent.c:2109
    #5 0x1003094dd in Tk_MainEx tkMain.c:376
    #6 0x100006c41 in main tkAppInit.c:93
    #7 0x7fff71c79cc8 in start+0x0 (libdyld.dylib:x86_64+0x1acc8)

0x614000087b38 is located 248 bytes inside of 424-byte region [0x614000087a40,0x614000087be8) freed by thread T0 here: #0 0x102e58999 in wrap_free+0xa9 (libclang_rt.asan_osx_dynamic.dylib:x86_64+0x46999) #1 0x101662a54 in TclpFree tclAlloc.c:722 #2 0x1023ffc40 in Tcl_EventuallyFree tclPreserve.c:294 #3 0x1003d8cf7 in Tk_DestroyWindow tkWindow.c:1693 #4 0x1001c00c7 in Tk_DestroyObjCmd tkCmds.c:500 #5 0x1016ec5c8 in Dispatch tclBasic.c:4467 #6 0x1016ccbfe in TclNRRunCallbacks tclBasic.c:4503 #7 0x1016caf6b in Tcl_EvalObjv tclBasic.c:4226 #8 0x1016d8abd in TclEvalEx tclBasic.c:5372 #9 0x1016d1a79 in Tcl_EvalEx tclBasic.c:5037 #10 0x10015c23d in Tk_BindEvent tkBind.c:2602 #11 0x1001bcc44 in TkBindEventProc tkCmds.c:319 #12 0x10022eb34 in Tk_HandleEvent tkEvent.c:1292 #13 0x1002364c0 in WindowEventProc tkEvent.c:1723 #14 0x1023519d8 in Tcl_ServiceEvent tclNotify.c:670 #15 0x10235363c in Tcl_DoOneEvent tclNotify.c:903 #16 0x10023a0af in Tk_MainLoop tkEvent.c:2109 #17 0x1003094dd in Tk_MainEx tkMain.c:376 #18 0x100006c41 in main tkAppInit.c:93 #19 0x7fff71c79cc8 in start+0x0 (libdyld.dylib:x86_64+0x1acc8)

I don’t see how Tcl_CancelIdleCall() can be used to avoid this issue (presumably the window data structure is managed by generic rather than Aqua code, and RefocusGrabWindow() is currently static). I would instead use Tcl_Preserve()/Tcl_Release() in applicationActivate: and RefocusGrabWindow() respectively (see attached patch), even though I’m not aware of usage elsewhere in core Tk for similar purposes (edit: there is an example of such usage in tkWinEmbed.c).

I’m not aware if this exact issue can occur with core-8-6-branch, but I would think the fix is still applicable, and for a long time I have occasionally encountered crashes involving grab and bgerror which were always too difficult to reproduce and so I never reported.

User Comments: jan.nijtmans added on 2025-11-04 20:45:06:

Proposed fix looks OK to me. Fixed [dc200f18af4a2f5e|here]


chrstphrchvz added on 2025-07-31 20:37:16:

Marc, I am not certain I understand what you’re asking. But you are correct that the lack of a crash for this issue is possible, especially when Tcl/Tk is built without -DPURIFY as that helps “hide” various memory errors (they either go unnoticed or cause more subtle problems than just immediately crashing); maybe that explains your observation. AddressSanitizer instead tries to treat such errors as fatal, which I find useful.


marc_culler (claiming to be Marc Culler) added on 2025-07-30 16:36:54:
Am I correct in thinking that this issue can be observed with AddressSanitizer
but does not actually cause a crash when running your test script? (That
was what I observed, anyway.)

Attachments: