From 27d00ef04f9ecbafef219105aa9dec4b54787b33 Mon Sep 17 00:00:00 2001
From: fvogel <fvogelnew1@free.fr>
Date: Sun, 28 Jan 2018 19:49:55 +0000
Subject: [PATCH 127/693] Fix [5d991b822e]: segmentation violation in
 TclObjLookupVarEx. Patch from Christian Werner.

---
 generic/tkButton.c     | 30 ++++++++++++++++++++++++++++--
 generic/tkEntry.c      | 17 +++++++++++++++--
 generic/tkListbox.c    | 17 +++++++++++++++--
 generic/tkMenu.c       | 11 +++++++++++
 generic/tkMenubutton.c | 13 +++++++++++++
 generic/tkMessage.c    | 13 +++++++++++++
 generic/tkScale.c      | 13 +++++++++++++
 generic/ttk/ttkTrace.c | 15 +++++++++++++--
 8 files changed, 121 insertions(+), 8 deletions(-)

diff --git a/generic/tkButton.c b/generic/tkButton.c
index b7e314e74..e114a5108 100644
--- a/generic/tkButton.c
+++ b/generic/tkButton.c
@@ -1610,6 +1610,19 @@ ButtonVarProc(
     const char *value;
     Tcl_Obj *valuePtr;
 
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (butPtr->selVarNamePtr == NULL) {
+	if (!(flags & TCL_INTERP_DESTROYED)) {
+	    Tcl_UntraceVar2(interp, name1, name2,
+		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		    ButtonVarProc, clientData);
+	}
+	return NULL;
+    }
+
     /*
      * If the variable is being unset, then just re-establish the trace unless
      * the whole interpreter is going away.
@@ -1692,8 +1705,8 @@ static char *
 ButtonTextVarProc(
     ClientData clientData,	/* Information about button. */
     Tcl_Interp *interp,		/* Interpreter containing variable. */
-    const char *name1,		/* Not used. */
-    const char *name2,		/* Not used. */
+    const char *name1,		/* Name of variable. */
+    const char *name2,		/* Second part of variable name. */
     int flags)			/* Information about what happened. */
 {
     TkButton *butPtr = clientData;
@@ -1703,6 +1716,19 @@ ButtonTextVarProc(
 	return NULL;
     }
 
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (butPtr->textVarNamePtr == NULL) {
+	if (!(flags & TCL_INTERP_DESTROYED)) {
+	    Tcl_UntraceVar2(interp, name1, name2,
+		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		    ButtonTextVarProc, clientData);
+	}
+ 	return NULL;
+     }
+ 
     /*
      * If the variable is unset, then immediately recreate it unless the whole
      * interpreter is going away.
diff --git a/generic/tkEntry.c b/generic/tkEntry.c
index 25774cc2f..678691fca 100644
--- a/generic/tkEntry.c
+++ b/generic/tkEntry.c
@@ -3135,8 +3135,8 @@ static char *
 EntryTextVarProc(
     ClientData clientData,	/* Information about button. */
     Tcl_Interp *interp,		/* Interpreter containing variable. */
-    const char *name1,		/* Not used. */
-    const char *name2,		/* Not used. */
+    const char *name1,		/* Name of variable. */
+    const char *name2,		/* Second part of variable name. */
     int flags)			/* Information about what happened. */
 {
     Entry *entryPtr = clientData;
@@ -3149,6 +3149,19 @@ EntryTextVarProc(
 	return NULL;
     }
 
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (entryPtr->textVarName == NULL) {
+	if (!(flags & TCL_INTERP_DESTROYED)) {
+	    Tcl_UntraceVar2(interp, name1, name2,
+		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		    EntryTextVarProc, clientData);
+	}
+ 	return NULL;
+     }
+
     /*
      * If the variable is unset, then immediately recreate it unless the whole
      * interpreter is going away.
diff --git a/generic/tkListbox.c b/generic/tkListbox.c
index b18a7f49f..5f650fed3 100644
--- a/generic/tkListbox.c
+++ b/generic/tkListbox.c
@@ -3431,8 +3431,8 @@ static char *
 ListboxListVarProc(
     ClientData clientData,	/* Information about button. */
     Tcl_Interp *interp,		/* Interpreter containing variable. */
-    const char *name1,		/* Not used. */
-    const char *name2,		/* Not used. */
+    const char *name1,		/* Name of variable. */
+    const char *name2,		/* Second part of variable name. */
     int flags)			/* Information about what happened. */
 {
     Listbox *listPtr = clientData;
@@ -3440,6 +3440,19 @@ ListboxListVarProc(
     int oldLength, i;
     Tcl_HashEntry *entry;
 
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (listPtr->listVarName == NULL) {
+	if (!(flags & TCL_INTERP_DESTROYED)) {
+	    Tcl_UntraceVar2(interp, name1, name2,
+		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		    ListboxListVarProc, clientData);
+	}
+	return NULL;
+    }
+
     /*
      * Bwah hahahaha! Puny mortal, you can't unset a -listvar'd variable!
      */
diff --git a/generic/tkMenu.c b/generic/tkMenu.c
index 42ddbd5ec..5859ac050 100644
--- a/generic/tkMenu.c
+++ b/generic/tkMenu.c
@@ -2500,6 +2500,17 @@ MenuVarProc(
     	return NULL;
     }
 
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (mePtr->namePtr == NULL) {
+	Tcl_UntraceVar2(interp, name1, name2,
+		TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		MenuVarProc, clientData);
+	return NULL;
+     }
+
     name = Tcl_GetString(mePtr->namePtr);
 
     /*
diff --git a/generic/tkMenubutton.c b/generic/tkMenubutton.c
index 1a4d5ae6e..2c1676c60 100644
--- a/generic/tkMenubutton.c
+++ b/generic/tkMenubutton.c
@@ -881,6 +881,19 @@ MenuButtonTextVarProc(
     const char *value;
     unsigned len;
 
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (mbPtr->textVarName == NULL) {
+	if (!(flags & TCL_INTERP_DESTROYED)) {
+	    Tcl_UntraceVar2(interp, name1, name2,
+		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		    MenuButtonTextVarProc, clientData);
+	}
+	return NULL;
+    }
+
     /*
      * If the variable is unset, then immediately recreate it unless the whole
      * interpreter is going away.
diff --git a/generic/tkMessage.c b/generic/tkMessage.c
index 2b7199875..f65b04687 100644
--- a/generic/tkMessage.c
+++ b/generic/tkMessage.c
@@ -838,6 +838,19 @@ MessageTextVarProc(
     register Message *msgPtr = clientData;
     const char *value;
 
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (msgPtr->textVarName == NULL) {
+	if (!(flags & TCL_INTERP_DESTROYED)) {
+	    Tcl_UntraceVar2(interp, name1, name2,
+		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		    MessageTextVarProc, clientData);
+	}
+	return NULL;
+    }
+
     /*
      * If the variable is unset, then immediately recreate it unless the whole
      * interpreter is going away.
diff --git a/generic/tkScale.c b/generic/tkScale.c
index ef67630d8..af45afa73 100644
--- a/generic/tkScale.c
+++ b/generic/tkScale.c
@@ -1192,6 +1192,19 @@ ScaleVarProc(
     Tcl_Obj *valuePtr;
     int result;
 
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (scalePtr->varNamePtr == NULL) {
+	if (!(flags & TCL_INTERP_DESTROYED)) {
+	    Tcl_UntraceVar2(interp, name1, name2,
+		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		    ScaleVarProc, clientData);
+	}
+	return NULL;
+    }
+
     /*
      * If the variable is unset, then immediately recreate it unless the whole
      * interpreter is going away.
diff --git a/generic/ttk/ttkTrace.c b/generic/ttk/ttkTrace.c
index ba66db427..e6eead2bc 100644
--- a/generic/ttk/ttkTrace.c
+++ b/generic/ttk/ttkTrace.c
@@ -26,8 +26,8 @@ static char *
 VarTraceProc(
     ClientData clientData,	/* Widget record pointer */
     Tcl_Interp *interp, 	/* Interpreter containing variable. */
-    const char *name1,		/* (unused) */
-    const char *name2,		/* (unused) */
+    const char *name1,		/* Name of variable. */
+    const char *name2,		/* Second part of variable name. */
     int flags)			/* Information about what happened. */
 {
     Ttk_TraceHandle *tracePtr = clientData;
@@ -38,6 +38,17 @@ VarTraceProc(
 	return NULL;
     }
 
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (tracePtr->varnameObj == NULL) {
+	Tcl_UntraceVar2(interp, name1, name2,
+		TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		VarTraceProc, clientData);
+	return NULL;
+    }
+
     name = Tcl_GetString(tracePtr->varnameObj);
 
     /*
-- 
2.19.1

