From b31544d53e672365f5838cc5f04c3c73b12401bd Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 5 Nov 2023 18:24:53 +0000 Subject: Final fix for Aqua menu crashes. --- generic/tkMenu.c | 1 + macosx/tkMacOSXMenu.c | 13 ++++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/generic/tkMenu.c b/generic/tkMenu.c index 7ca930b..8a7e892 100644 --- a/generic/tkMenu.c +++ b/generic/tkMenu.c @@ -1179,6 +1179,7 @@ DestroyMenuInstance( Tcl_EventuallyFree(menuPtr->entries[i], DestroyMenuEntry); menuPtr->numEntries = i; } + menuPtr->active = -1; if (menuPtr->entries != NULL) { ckfree(menuPtr->entries); menuPtr->entries = NULL; diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c index 7a69876..b510422 100644 --- a/macosx/tkMacOSXMenu.c +++ b/macosx/tkMacOSXMenu.c @@ -888,14 +888,17 @@ TkpDestroyMenuEntry( TKMenu *menu; NSInteger index; - if (mePtr->platformEntryData && mePtr->menuPtr->platformData) { - menu = (TKMenu *) mePtr->menuPtr->platformData; + if (mePtr->platformEntryData) { menuItem = (NSMenuItem *) mePtr->platformEntryData; - index = [menu indexOfItem:menuItem]; + if (mePtr->menuPtr->platformData) { + menu = (TKMenu *) mePtr->menuPtr->platformData; + index = [menu indexOfItem:menuItem]; - if (index > -1) { - [menu removeItemAtIndex:index]; + if (index > -1) { + [menu removeItemAtIndex:index]; + } } + [menuItem setTag:(NSInteger) NULL]; [menuItem release]; mePtr->platformEntryData = NULL; } -- cgit v0.12 From 2a8295a85980689be52753cd965b099c90233257 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 5 Nov 2023 19:36:27 +0000 Subject: Add a non-regression test for the invoke crash. --- tests/menu.test | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/menu.test b/tests/menu.test index 68d432b..e1b4d91 100644 --- a/tests/menu.test +++ b/tests/menu.test @@ -14,6 +14,7 @@ imageInit # find the earth.gif file for use in these tests (tests 2.*) set earthPhotoFile [file join [file dirname [info script]] earth.gif] testConstraint hasEarthPhoto [file exists $earthPhotoFile] +testConstraint pressbutton [llength [info commands pressbutton]] test menu-1.1 {Tk_MenuCmd procedure} -body { menu @@ -4110,6 +4111,20 @@ test menu-39.2 {use-after-free fix - bug 1797555fff} -setup { destroy .t } -result {} +test menu-40.1 {Use-after-free if menu destroyed while posted - bug 09a11fb1228f} -setup { +} -constraints {pressbutton} -body { + set done false + toplevel .t + menu .t.m + .t.m add command -command {puts Marco} -label Marco + .t.m add command -command {puts Polo} -label Polo + event generate {} -warp 1 -x 100 -y 100 + after 1000 {.t.m post 500 500} + after 3000 {destroy .t} + after 3500 {pressbutton 530 510} + after 4000 {set done true} + tkwait variable done +} # cleanup imageFinish -- cgit v0.12 From 0b938d91fdc784a0db3bdcc3f524a7fbc199c0f5 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 5 Nov 2023 20:46:56 +0000 Subject: Add non-regression test for the 'activate' case --- macosx/tkMacOSXTest.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++ tests/menu.test | 25 ++++++++++++++-- 2 files changed, 103 insertions(+), 3 deletions(-) diff --git a/macosx/tkMacOSXTest.c b/macosx/tkMacOSXTest.c index 3f178c3..82c207d 100644 --- a/macosx/tkMacOSXTest.c +++ b/macosx/tkMacOSXTest.c @@ -25,6 +25,7 @@ static Tcl_ObjCmdProc DebuggerObjCmd; #endif static Tcl_ObjCmdProc PressButtonObjCmd; +static Tcl_ObjCmdProc MoveMouseObjCmd; static Tcl_ObjCmdProc InjectKeyEventObjCmd; static Tcl_ObjCmdProc MenuBarHeightObjCmd; @@ -58,6 +59,7 @@ TkplatformtestInit( Tcl_CreateObjCommand(interp, "debugger", DebuggerObjCmd, NULL, NULL); #endif Tcl_CreateObjCommand(interp, "pressbutton", PressButtonObjCmd, NULL, NULL); + Tcl_CreateObjCommand(interp, "movemouse", MoveMouseObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "injectkeyevent", InjectKeyEventObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "menubarheight", MenuBarHeightObjCmd, NULL, NULL); return TCL_OK; @@ -266,6 +268,85 @@ PressButtonObjCmd( return TCL_OK; } +/* + *---------------------------------------------------------------------- + * + * MoveMouseObjCmd -- + * + * This Tcl command simulates a mouse motion to a specific screen + * location. It injects an NSEvent into the NSApplication event queue, + * as opposed to adding events to the Tcl queue as event generate would + * do. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +MoveMouseObjCmd( + TCL_UNUSED(void *), + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ + int x = 0, y = 0, i, value; + CGPoint pt; + NSPoint loc; + NSEvent *motion; + NSArray *screens = [NSScreen screens]; + CGFloat ScreenHeight = 0; + enum {X=1, Y}; + + if (screens && [screens count]) { + ScreenHeight = [[screens objectAtIndex:0] frame].size.height; + } + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "x y"); + return TCL_ERROR; + } + for (i = 1; i < objc; i++) { + if (Tcl_GetIntFromObj(interp,objv[i],&value) != TCL_OK) { + return TCL_ERROR; + } + switch (i) { + case X: + x = value; + break; + case Y: + y = value; + break; + default: + break; + } + } + pt.x = loc.x = x; + pt.y = y; + loc.y = ScreenHeight - y; + + /* + * We set the timestamp to 0 as a signal to tkProcessMouseEvent. + */ + + CGWarpMouseCursorPosition(pt); + motion = [NSEvent mouseEventWithType:NSMouseMoved + location:loc + modifierFlags:0 + timestamp:0 + windowNumber:0 + context:nil + eventNumber:0 + clickCount:1 + pressure:0]; + [NSApp postEvent:motion atStart:NO]; + return TCL_OK; +} + static int InjectKeyEventObjCmd( TCL_UNUSED(void *), diff --git a/tests/menu.test b/tests/menu.test index e1b4d91..23c28b0 100644 --- a/tests/menu.test +++ b/tests/menu.test @@ -15,6 +15,7 @@ imageInit set earthPhotoFile [file join [file dirname [info script]] earth.gif] testConstraint hasEarthPhoto [file exists $earthPhotoFile] testConstraint pressbutton [llength [info commands pressbutton]] +testConstraint movemouse [llength [info commands movemouse]] test menu-1.1 {Tk_MenuCmd procedure} -body { menu @@ -4114,16 +4115,34 @@ test menu-39.2 {use-after-free fix - bug 1797555fff} -setup { test menu-40.1 {Use-after-free if menu destroyed while posted - bug 09a11fb1228f} -setup { } -constraints {pressbutton} -body { set done false + event generate {} -x 100 -y 100 toplevel .t menu .t.m .t.m add command -command {puts Marco} -label Marco .t.m add command -command {puts Polo} -label Polo - event generate {} -warp 1 -x 100 -y 100 after 1000 {.t.m post 500 500} + after 2000 {destroy .t} + after 2500 {pressbutton 530 510} + after 3000 {set done true} + tkwait variable done +} + +test menu-40.2 {Use-after-free if menu destroyed while posted - bug 09a11fb1228f} -setup { +} -constraints {movemouse} -body { + set done false + event generate {} -x 100 -y 100 + toplevel .t + menu .t.m + .t.m add command -command {puts Marco} -label Marco + .t.m add command -command {puts Polo} -label Polo + after 1000 {.t.m post 500 500} + after 2000 {movemouse 530 510} after 3000 {destroy .t} - after 3500 {pressbutton 530 510} - after 4000 {set done true} + after 3500 {movemouse 530 530} + after 4000 pressbutton 530 530 + after 4500 {set done true} tkwait variable done + pressbutton 530 510 } # cleanup -- cgit v0.12 From c204c52d17a81ae11cc9722cdc8f403a3794afb1 Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 6 Nov 2023 15:36:58 +0000 Subject: Trigger a CI build of this branch. --- .github/workflows/linux-build.yml | 1 + .github/workflows/mac-build.yml | 1 + .github/workflows/win-build.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index d594c0c..811f7b6 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -4,6 +4,7 @@ on: branches: - "main" - "core-8-6-branch" + - "bug-09a11fb1228f-final" tags: - "core-**" permissions: diff --git a/.github/workflows/mac-build.yml b/.github/workflows/mac-build.yml index 6c06a55..913e1a7 100644 --- a/.github/workflows/mac-build.yml +++ b/.github/workflows/mac-build.yml @@ -4,6 +4,7 @@ on: branches: - "main" - "core-8-6-branch" + - "bug-09a11fb1228f-final" tags: - "core-**" permissions: diff --git a/.github/workflows/win-build.yml b/.github/workflows/win-build.yml index 75f3a99..a3b825d 100644 --- a/.github/workflows/win-build.yml +++ b/.github/workflows/win-build.yml @@ -4,6 +4,7 @@ on: branches: - "main" - "core-8-6-branch" + - "bug-09a11fb1228f-final" tags: - "core-**" permissions: -- cgit v0.12