From f0ac004c7b9eb1d05be53e4b764e81076d314c6f Mon Sep 17 00:00:00 2001
From: fvogel <fvogelnew1@free.fr>
Date: Mon, 29 Jan 2018 21:32:53 +0000
Subject: [PATCH 131/693] Fix [502e74e9ad]: crash for untrusted X connections
 (for ssh: ForwardX11Trusted no). Patch from Christian Werner.

---
 unix/tkUnixSend.c | 66 ++++++++++++++++++++++++++++++-----------------
 1 file changed, 42 insertions(+), 24 deletions(-)

diff --git a/unix/tkUnixSend.c b/unix/tkUnixSend.c
index bbbdd774c..95e5ae27e 100644
--- a/unix/tkUnixSend.c
+++ b/unix/tkUnixSend.c
@@ -261,11 +261,14 @@ RegOpen(
     unsigned long bytesAfter;
     Atom actualType;
     char **propertyPtr;
+    Tk_ErrorHandler handler;
 
     if (dispPtr->commTkwin == NULL) {
 	SendInit(interp, dispPtr);
     }
 
+    handler = Tk_CreateErrorHandler(dispPtr->display, -1, -1, -1, NULL, NULL);
+
     regPtr = ckalloc(sizeof(NameRegistry));
     regPtr->dispPtr = dispPtr;
     regPtr->locked = 0;
@@ -306,8 +309,11 @@ RegOpen(
 	XDeleteProperty(dispPtr->display,
 		RootWindow(dispPtr->display, 0),
 		dispPtr->registryProperty);
+        XSync(dispPtr->display, False);
     }
 
+    Tk_DeleteErrorHandler(handler);
+
     /*
      * Xlib placed an extra null byte after the end of the property, just to
      * make sure that it is always NULL-terminated. Be sure to include this
@@ -514,6 +520,11 @@ RegClose(
     NameRegistry *regPtr)	/* Pointer to a registry opened with a
 				 * previous call to RegOpen. */
 {
+    Tk_ErrorHandler handler;
+
+    handler = Tk_CreateErrorHandler(regPtr->dispPtr->display, -1, -1, -1,
+            NULL, NULL);
+
     if (regPtr->modified) {
 	if (!regPtr->locked && !localData.sendDebug) {
 	    Tcl_Panic("The name registry was modified without being locked!");
@@ -540,6 +551,8 @@ RegClose(
 
     XFlush(regPtr->dispPtr->display);
 
+    Tk_DeleteErrorHandler(handler);
+
     if (regPtr->property != NULL) {
 	if (regPtr->allocedByX) {
 	    XFree(regPtr->property);
@@ -1095,6 +1108,31 @@ Tk_SendObjCmd(
 	Tcl_DStringAppend(&request, " ", 1);
 	Tcl_DStringAppend(&request, Tcl_GetString(objv[i]), -1);
     }
+
+    if (!async) {
+	/*
+	 * Register the fact that we're waiting for a command to complete
+	 * (this is needed by SendEventProc and by AppendErrorProc to pass
+	 * back the command's results). Set up a timeout handler so that
+	 * we can check during long sends to make sure that the destination
+	 * application is still alive.
+	 *
+	 * We prepare the pending struct here in order to catch potential
+	 * early X errors from AppendPropCarefully() due to XSync().
+	 */
+
+	pending.serial = localData.sendSerial;
+	pending.dispPtr = dispPtr;
+	pending.target = destName;
+	pending.commWindow = commWindow;
+	pending.interp = interp;
+	pending.result = NULL;
+	pending.errorInfo = NULL;
+	pending.errorCode = NULL;
+	pending.gotResponse = 0;
+	pending.nextPtr = tsdPtr->pendingCommands;
+	tsdPtr->pendingCommands = &pending;
+    }
     (void) AppendPropCarefully(dispPtr->display, commWindow,
 	    dispPtr->commProperty, Tcl_DStringValue(&request),
 	    Tcl_DStringLength(&request) + 1, (async ? NULL : &pending));
@@ -1108,26 +1146,6 @@ Tk_SendObjCmd(
 	return TCL_OK;
     }
 
-    /*
-     * Register the fact that we're waiting for a command to complete (this is
-     * needed by SendEventProc and by AppendErrorProc to pass back the
-     * command's results). Set up a timeout handler so that we can check
-     * during long sends to make sure that the destination application is
-     * still alive.
-     */
-
-    pending.serial = localData.sendSerial;
-    pending.dispPtr = dispPtr;
-    pending.target = destName;
-    pending.commWindow = commWindow;
-    pending.interp = interp;
-    pending.result = NULL;
-    pending.errorInfo = NULL;
-    pending.errorCode = NULL;
-    pending.gotResponse = 0;
-    pending.nextPtr = tsdPtr->pendingCommands;
-    tsdPtr->pendingCommands = &pending;
-
     /*
      * Enter a loop processing X events until the result comes in or the
      * target is declared to be dead. While waiting for a result, look only at
@@ -1959,11 +1977,11 @@ TkpTestsendCmd(
 	return TCL_ERROR;
     }
 
-	if (Tcl_GetIndexFromObjStruct(interp, objv[1], testsendOptions,
+    if (Tcl_GetIndexFromObjStruct(interp, objv[1], testsendOptions,
 		sizeof(char *), "option", 0, &index) != TCL_OK) {
-	    return TCL_ERROR;
-	}
-	if (index == TESTSEND_BOGUS) {
+	return TCL_ERROR;
+    }
+    if (index == TESTSEND_BOGUS) {
 	XChangeProperty(winPtr->dispPtr->display,
 		RootWindow(winPtr->dispPtr->display, 0),
 		winPtr->dispPtr->registryProperty, XA_INTEGER, 32,
-- 
2.19.1

