From 3a509540d384f5f707a39987642f1f111e4bf657 Mon Sep 17 00:00:00 2001 From: dgp Date: Sat, 11 May 2019 20:36:25 +0000 Subject: Tests for Ticket [5d991b822e]. --- tests/button.test | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/button.test b/tests/button.test index d4db317..21ccf8f 100644 --- a/tests/button.test +++ b/tests/button.test @@ -3958,6 +3958,33 @@ test button-14.1 {bug fix: [011706ec42] tk::ButtonInvoke unsafe wrt widget destr destroy .top.b .top } -result {} +test button-15.1 {Bug [5d991b822e]} { + # Want this not to segfault + set var INIT + button .b -textvariable var + trace add variable var unset {apply {args { + .b configure -textvariable {} + }}} + pack .b + bind .b {unset var} + update + destroy .b +} {} +test button-15.2 {Bug [5d991b822e]} { + # Want this not to leak traces + set var INIT + button .b -textvariable var + trace add variable var unset {apply {args { + .b configure -textvariable new + }}} + pack .b + bind .b {unset var} + update + destroy .b + unset new +} {} + + imageFinish cleanupTests return -- cgit v0.12 From 6721be522c279e1343d675072819bd1671b40fe8 Mon Sep 17 00:00:00 2001 From: dgp Date: Sat, 11 May 2019 20:53:22 +0000 Subject: Fix for the [button ... -textvariable] parts of [5d991b822e]. --- generic/tkButton.c | 29 ++++++++++++++++++++++++++++- tests/button.test | 2 +- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/generic/tkButton.c b/generic/tkButton.c index b7e314e..0e1a4e9 100644 --- a/generic/tkButton.c +++ b/generic/tkButton.c @@ -1709,7 +1709,34 @@ ButtonTextVarProc( */ if (flags & TCL_TRACE_UNSETS) { - if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { + if (!Tcl_InterpDeleted(interp) && butPtr->textVarNamePtr != NULL) { + + /* + * An unset trace on some variable brought us here, but is it + * the variable we have stored in butPtr->textVarNamePtr ? + */ + + ClientData probe = NULL; + + do { + probe = Tcl_VarTraceInfo(interp, + Tcl_GetString(butPtr->textVarNamePtr), + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + ButtonTextVarProc, probe); + if (probe == (ClientData)butPtr) { + break; + } + } while (probe); + if (probe) { + /* + * We were able to fetch the unset trace for our + * textVarNamePtr, which means it is not unset and not + * the cause of this unset trace. Instead some outdated + * former textvariable must be, and we should ignore it. + */ + return NULL; + } + Tcl_ObjSetVar2(interp, butPtr->textVarNamePtr, NULL, butPtr->textPtr, TCL_GLOBAL_ONLY); Tcl_TraceVar2(interp, Tcl_GetString(butPtr->textVarNamePtr), diff --git a/tests/button.test b/tests/button.test index 21ccf8f..edc5a42 100644 --- a/tests/button.test +++ b/tests/button.test @@ -3978,7 +3978,7 @@ test button-15.2 {Bug [5d991b822e]} { .b configure -textvariable new }}} pack .b - bind .b {unset var} + bind .b {unset -nocomplain var} update destroy .b unset new -- cgit v0.12 From 01e6edbdb423d22ea06fb1cfafa3fa0691265d07 Mon Sep 17 00:00:00 2001 From: dgp Date: Sun, 12 May 2019 23:15:19 +0000 Subject: Similar test and fix for [checkbutton ... -variable]. --- generic/tkButton.c | 22 +++++++++++++++++++++- tests/button.test | 12 ++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/generic/tkButton.c b/generic/tkButton.c index 0e1a4e9..f3bdbfb 100644 --- a/generic/tkButton.c +++ b/generic/tkButton.c @@ -1617,7 +1617,27 @@ ButtonVarProc( if (flags & TCL_TRACE_UNSETS) { butPtr->flags &= ~(SELECTED | TRISTATED); - if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { + if (!Tcl_InterpDeleted(interp)) { + ClientData probe = NULL; + + do { + probe = Tcl_VarTraceInfo(interp, + Tcl_GetString(butPtr->selVarNamePtr), + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + ButtonVarProc, probe); + if (probe == (ClientData)butPtr) { + break; + } + } while (probe); + if (probe) { + /* + * We were able to fetch the unset trace for our + * selVarNamePtr, which means it is not unset and not + * the cause of this unset trace. Instead some outdated + * former variable must be, and we should ignore it. + */ + goto redisplay; + } Tcl_TraceVar2(interp, Tcl_GetString(butPtr->selVarNamePtr), NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonVarProc, clientData); diff --git a/tests/button.test b/tests/button.test index edc5a42..b953197 100644 --- a/tests/button.test +++ b/tests/button.test @@ -3983,6 +3983,18 @@ test button-15.2 {Bug [5d991b822e]} { destroy .b unset new } {} +test button-15.3 {Bug [5d991b822e]} { + # Want this not to leak traces + set var INIT + checkbutton .b -variable var + trace add variable var unset {apply {args { + .b configure -variable {} + }}} + pack .b + bind .b {unset var} + update + destroy .b +} {} imageFinish -- cgit v0.12 From 8760f6459a6dc7b1902f830af8bcb4b1bbdca2d5 Mon Sep 17 00:00:00 2001 From: dgp Date: Sun, 12 May 2019 23:56:49 +0000 Subject: Similar tests and fix for [entry .... -textvariable] --- generic/tkEntry.c | 24 ++++++++++++++++++++++-- tests/entry.test | 28 ++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/generic/tkEntry.c b/generic/tkEntry.c index 25774cc..0817952 100644 --- a/generic/tkEntry.c +++ b/generic/tkEntry.c @@ -3155,14 +3155,34 @@ EntryTextVarProc( */ if (flags & TCL_TRACE_UNSETS) { - if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { + if (!Tcl_InterpDeleted(interp) && entryPtr->textVarName) { + ClientData probe = NULL; + + do { + probe = Tcl_VarTraceInfo(interp, + entryPtr->textVarName, + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + EntryTextVarProc, probe); + if (probe == (ClientData)entryPtr) { + break; + } + } while (probe); + if (probe) { + /* + * We were able to fetch the unset trace for our + * textVarName, which means it is not unset and not + * the cause of this unset trace. Instead some outdated + * former variable must be, and we should ignore it. + */ + return NULL; + } Tcl_SetVar2(interp, entryPtr->textVarName, NULL, entryPtr->string, TCL_GLOBAL_ONLY); Tcl_TraceVar2(interp, entryPtr->textVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, EntryTextVarProc, clientData); entryPtr->flags |= ENTRY_VAR_TRACED; - } + } return NULL; } diff --git a/tests/entry.test b/tests/entry.test index fbaf6a5..67f8374 100644 --- a/tests/entry.test +++ b/tests/entry.test @@ -3502,6 +3502,34 @@ test entry-24.1 {textvariable lives in a non-existing namespace} -setup { destroy .e } -result {can't trace "thisnsdoesntexist::myvar": parent namespace doesn't exist} +test entry-25.1 {Bug [5d991b822e]} { + # Want this not to segfault, or write to variable with empty name + set var INIT + entry .b -textvariable var + trace add variable var unset {apply {args { + .b configure -textvariable {} + }}} + pack .b + bind .b {unset var} + update + destroy .b + info exists {} +} 0 +test entry-25.2 {Bug [5d991b822e]} { + # Want this not to leak traces + set var INIT + entry .b -textvariable var + trace add variable var unset {apply {args { + .b configure -textvariable new + }}} + pack .b + bind .b {unset -nocomplain var} + update + destroy .b + unset new +} {} + + # Gathered comments about lacks # XXX Still need to write tests for EntryBlinkProc, EntryFocusProc, # and EntryTextVarProc. -- cgit v0.12 From 7f33552ef446220a57674a0350a829fbf08451de Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 15 May 2019 17:01:05 +0000 Subject: Tests for same issues with [listbox ... -listvariable]. --- tests/listbox.test | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/listbox.test b/tests/listbox.test index 99c84a7..2c07633 100644 --- a/tests/listbox.test +++ b/tests/listbox.test @@ -3177,6 +3177,33 @@ test listbox-31.2 {<> event on lost selection} -setup { destroy .l } -result {{.l 0} {{} {}}} +test listbox-32.1 {Bug [5d991b822e]} { + # Want this not to segfault, or write to variable with empty name + set var INIT + listbox .b -listvariable var + trace add variable var unset {apply {args { + .b configure -listvariable {} + }}} + pack .b + bind .b {unset var} + update + destroy .b + info exists {} +} 0 +test listbox-32.2 {Bug [5d991b822e]} { + # Want this not to leak traces + set var INIT + listbox .b -listvariable var + trace add variable var unset {apply {args { + .b configure -listvariable new + }}} + pack .b + bind .b {unset -nocomplain var} + update + destroy .b + unset new +} {} + resetGridInfo deleteWindows option clear -- cgit v0.12 From 9c596d150ad96b9e928fb86d4dad82ebfcefa2d2 Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 15 May 2019 17:08:01 +0000 Subject: Fix for the failing/crashing listbox tests. --- generic/tkListbox.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/generic/tkListbox.c b/generic/tkListbox.c index b18a7f4..de85d51 100644 --- a/generic/tkListbox.c +++ b/generic/tkListbox.c @@ -3445,7 +3445,28 @@ ListboxListVarProc( */ if (flags & TCL_TRACE_UNSETS) { - if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { + + if (!Tcl_InterpDeleted(interp) && listPtr->listVarName) { + ClientData probe = NULL; + + do { + probe = Tcl_VarTraceInfo(interp, + listPtr->listVarName, + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + ListboxListVarProc, probe); + if (probe == (ClientData)listPtr) { + break; + } + } while (probe); + if (probe) { + /* + * We were able to fetch the unset trace for our + * listVarName, which means it is not unset and not + * the cause of this unset trace. Instead some outdated + * former variable must be, and we should ignore it. + */ + return NULL; + } Tcl_SetVar2Ex(interp, listPtr->listVarName, NULL, listPtr->listObj, TCL_GLOBAL_ONLY); Tcl_TraceVar2(interp, listPtr->listVarName, -- cgit v0.12 From 1673645f691d6a028123a612d5476541b8305d91 Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 15 May 2019 17:16:15 +0000 Subject: Tests and fix for [menubutton ... -textvariable]. --- generic/tkMenubutton.c | 22 +++++++++++++++++++++- tests/menubut.test | 28 ++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/generic/tkMenubutton.c b/generic/tkMenubutton.c index 1a4d5ae..9faa263 100644 --- a/generic/tkMenubutton.c +++ b/generic/tkMenubutton.c @@ -887,7 +887,27 @@ MenuButtonTextVarProc( */ if (flags & TCL_TRACE_UNSETS) { - if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { + if (!Tcl_InterpDeleted(interp) && mbPtr->textVarName) { + ClientData probe = NULL; + + do { + probe = Tcl_VarTraceInfo(interp, + mbPtr->textVarName, + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + MenuButtonTextVarProc, probe); + if (probe == (ClientData)mbPtr) { + break; + } + } while (probe); + if (probe) { + /* + * We were able to fetch the unset trace for our + * textVarName, which means it is not unset and not + * the cause of this unset trace. Instead some outdated + * former variable must be, and we should ignore it. + */ + return NULL; + } Tcl_SetVar2(interp, mbPtr->textVarName, NULL, mbPtr->text, TCL_GLOBAL_ONLY); Tcl_TraceVar2(interp, mbPtr->textVarName, NULL, diff --git a/tests/menubut.test b/tests/menubut.test index 6efdb0f..93b2482 100644 --- a/tests/menubut.test +++ b/tests/menubut.test @@ -747,6 +747,34 @@ test menubutton-8.1 {menubutton vs hidden commands} -body { expr {$res1 eq $res2} } -result 1 +test menubutton-9.1 {Bug [5d991b822e]} { + # Want this not to segfault, or write to variable with empty name + set var INIT + menubutton .b -textvariable var + trace add variable var unset {apply {args { + .b configure -textvariable {} + }}} + pack .b + bind .b {unset var} + update + destroy .b + info exists {} +} 0 +test menubutton-9.2 {Bug [5d991b822e]} { + # Want this not to leak traces + set var INIT + menubutton .b -textvariable var + trace add variable var unset {apply {args { + .b configure -textvariable new + }}} + pack .b + bind .b {unset -nocomplain var} + update + destroy .b + unset new +} {} + + deleteWindows -- cgit v0.12 From 53669ac6b8743ed34a13bcb8d68521966b4d479a Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 15 May 2019 17:20:54 +0000 Subject: Tests and fix for [message ... -textvariable]. --- generic/tkMessage.c | 22 +++++++++++++++++++++- tests/message.test | 27 +++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/generic/tkMessage.c b/generic/tkMessage.c index 2b71998..1508beb 100644 --- a/generic/tkMessage.c +++ b/generic/tkMessage.c @@ -844,7 +844,27 @@ MessageTextVarProc( */ if (flags & TCL_TRACE_UNSETS) { - if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { + if (!Tcl_InterpDeleted(interp) && msgPtr->textVarName) { + ClientData probe = NULL; + + do { + probe = Tcl_VarTraceInfo(interp, + msgPtr->textVarName, + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + MessageTextVarProc, probe); + if (probe == (ClientData)msgPtr) { + break; + } + } while (probe); + if (probe) { + /* + * We were able to fetch the unset trace for our + * textVarName, which means it is not unset and not + * the cause of this unset trace. Instead some outdated + * former variable must be, and we should ignore it. + */ + return NULL; + } Tcl_SetVar2(interp, msgPtr->textVarName, NULL, msgPtr->string, TCL_GLOBAL_ONLY); Tcl_TraceVar2(interp, msgPtr->textVarName, NULL, diff --git a/tests/message.test b/tests/message.test index dcffc72..cc2e0d0 100644 --- a/tests/message.test +++ b/tests/message.test @@ -470,5 +470,32 @@ test message-3.7 {MessageWidgetObjCmd procedure, "configure"} -setup { destroy .m } -result {4} +test message-4.1 {Bug [5d991b822e]} { + # Want this not to segfault, or write to variable with empty name + set var INIT + message .b -textvariable var + trace add variable var unset {apply {args { + .b configure -textvariable {} + }}} + pack .b + bind .b {unset var} + update + destroy .b + info exists {} +} 0 +test message-4.2 {Bug [5d991b822e]} { + # Want this not to leak traces + set var INIT + message .b -textvariable var + trace add variable var unset {apply {args { + .b configure -textvariable new + }}} + pack .b + bind .b {unset -nocomplain var} + update + destroy .b + unset new +} {} + cleanupTests return -- cgit v0.12 From aefe754799655f3fa04cc84f4ea5d110d0289c46 Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 15 May 2019 17:30:35 +0000 Subject: Tests and fix for [scale ... -variable]. --- generic/tkScale.c | 23 ++++++++++++++++++++++- tests/scale.test | 26 ++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/generic/tkScale.c b/generic/tkScale.c index ef67630..3920aea 100644 --- a/generic/tkScale.c +++ b/generic/tkScale.c @@ -1198,7 +1198,28 @@ ScaleVarProc( */ if (flags & TCL_TRACE_UNSETS) { - if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { + + if (!Tcl_InterpDeleted(interp) && scalePtr->varNamePtr) { + ClientData probe = NULL; + + do { + probe = Tcl_VarTraceInfo(interp, + Tcl_GetString(scalePtr->varNamePtr), + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + ScaleVarProc, probe); + if (probe == (ClientData)scalePtr) { + break; + } + } while (probe); + if (probe) { + /* + * We were able to fetch the unset trace for our + * varNamePtr, which means it is not unset and not + * the cause of this unset trace. Instead some outdated + * former variable must be, and we should ignore it. + */ + return NULL; + } Tcl_TraceVar2(interp, Tcl_GetString(scalePtr->varNamePtr), NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ScaleVarProc, clientData); diff --git a/tests/scale.test b/tests/scale.test index 79524eb..ba70285 100644 --- a/tests/scale.test +++ b/tests/scale.test @@ -1524,6 +1524,32 @@ test scale-21.2 {Bug [55b95f578a] again - Bignum value for -from/-to with scale destroy .s } -result {} +test scale-22.1 {Bug [5d991b822e]} { + # Want this not to crash + set var INIT + scale .b -variable var + trace add variable var unset {apply {args { + .b configure -variable {} + }}} + pack .b + bind .b {unset var} + update + destroy .b +} {} +test scale-22.2 {Bug [5d991b822e]} { + # Want this not to leak traces + set var INIT + scale .b -variable var + trace add variable var unset {apply {args { + .b configure -variable new + }}} + pack .b + bind .b {unset -nocomplain var} + update + destroy .b + unset new +} {} + option clear # cleanup -- cgit v0.12 From 273f03adcc49bca49f4941c8adb241b5ccc26c25 Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 15 May 2019 18:05:47 +0000 Subject: Tests and fix for similar issues in [menu]. --- generic/tkMenu.c | 32 +++++++++++++++++++++++++------- generic/tkScale.c | 1 - tests/menu.test | 28 ++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/generic/tkMenu.c b/generic/tkMenu.c index 42ddbd5..d7f5858 100644 --- a/generic/tkMenu.c +++ b/generic/tkMenu.c @@ -2486,9 +2486,10 @@ MenuVarProc( const char *value; const char *name, *onValue; - if (flags & TCL_INTERP_DESTROYED) { + if (Tcl_InterpDeleted(interp) || (mePtr->namePtr == NULL)) { /* - * Do nothing if the interpreter is going away. + * Do nothing if the interpreter is going away or we have + * no variable name. */ return NULL; @@ -2507,12 +2508,29 @@ MenuVarProc( */ if (flags & TCL_TRACE_UNSETS) { + ClientData probe = NULL; mePtr->entryFlags &= ~ENTRY_SELECTED; - if (flags & TCL_TRACE_DESTROYED) { - Tcl_TraceVar2(interp, name, NULL, - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, - MenuVarProc, clientData); - } + + do { + probe = Tcl_VarTraceInfo(interp, name, + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + MenuVarProc, probe); + if (probe == (ClientData)mePtr) { + break; + } + } while (probe); + if (probe) { + /* + * We were able to fetch the unset trace for our + * namePtr, which means it is not unset and not + * the cause of this unset trace. Instead some outdated + * former variable must be, and we should ignore it. + */ + return NULL; + } + Tcl_TraceVar2(interp, name, NULL, + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + MenuVarProc, clientData); TkpConfigureMenuEntry(mePtr); TkEventuallyRedrawMenu(menuPtr, NULL); return NULL; diff --git a/generic/tkScale.c b/generic/tkScale.c index 3920aea..4630170 100644 --- a/generic/tkScale.c +++ b/generic/tkScale.c @@ -1198,7 +1198,6 @@ ScaleVarProc( */ if (flags & TCL_TRACE_UNSETS) { - if (!Tcl_InterpDeleted(interp) && scalePtr->varNamePtr) { ClientData probe = NULL; diff --git a/tests/menu.test b/tests/menu.test index 95699ff..9378686 100644 --- a/tests/menu.test +++ b/tests/menu.test @@ -3162,6 +3162,34 @@ test menu-17.5 {MenuVarProc} -setup { } -cleanup { deleteWindows } -result {{} goodbye {}} +test menu-17.6 {MenuVarProc [5d991b822e]} -setup { + deleteWindows +} -body { + # Want this not to crash + menu .b + set var INIT + .b add checkbutton -variable var + trace add variable var unset {apply {args { + .b entryconfigure 1 -variable {} + }}} + unset var +} -cleanup { + deleteWindows +} -result {} +test menu-17.7 {MenuVarProc [5d991b822e]} -setup { + deleteWindows +} -body { + # Want this not to duplicate traces + menu .b + set var INIT + .b add checkbutton -variable var + trace add variable var unset {apply {args { + .b entryconfigure 1 -variable new + }}} + unset var +} -cleanup { + deleteWindows +} -result {} test menu-18.1 {TkActivateMenuEntry} -setup { -- cgit v0.12