From f0ac004c7b9eb1d05be53e4b764e81076d314c6f Mon Sep 17 00:00:00 2001 From: fvogel 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