0 | |
Author: Upstream
|
1 | |
Description: Patch fixes crashing when a TK application is used over untrusted
|
2 | |
X connections.
|
3 | |
Last-Modified: Sat, 24 Mar 2018 16:25:40 +0300
|
4 | |
Bug: http://core.tcl.tk/tk/tktview?name=502e74e9ad198e5239092356333aceba5c6ab47a
|
5 | |
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=888581
|
6 | |
|
7 | |
--- a/generic/tkCmds.c
|
8 | |
+++ b/generic/tkCmds.c
|
9 | |
@@ -101,6 +101,7 @@
|
10 | |
enum options { TK_BELL_DISPLAYOF, TK_BELL_NICE };
|
11 | |
Tk_Window tkwin = clientData;
|
12 | |
int i, index, nice = 0;
|
13 | |
+ Tk_ErrorHandler handler;
|
14 | |
|
15 | |
if (objc > 4) {
|
16 | |
wrongArgs:
|
17 | |
@@ -128,11 +129,13 @@
|
18 | |
break;
|
19 | |
}
|
20 | |
}
|
21 | |
+ handler = Tk_CreateErrorHandler(Tk_Display(tkwin), -1, -1, -1, NULL, NULL);
|
22 | |
XBell(Tk_Display(tkwin), 0);
|
23 | |
if (!nice) {
|
24 | |
XForceScreenSaver(Tk_Display(tkwin), ScreenSaverReset);
|
25 | |
}
|
26 | |
XFlush(Tk_Display(tkwin));
|
27 | |
+ Tk_DeleteErrorHandler(handler);
|
28 | |
return TCL_OK;
|
29 | |
}
|
30 | |
|
31 | |
--- a/unix/tkUnixSend.c
|
32 | |
+++ b/unix/tkUnixSend.c
|
33 | |
@@ -261,11 +261,14 @@
|
34 | |
unsigned long bytesAfter;
|
35 | |
Atom actualType;
|
36 | |
char **propertyPtr;
|
37 | |
+ Tk_ErrorHandler handler;
|
38 | |
|
39 | |
if (dispPtr->commTkwin == NULL) {
|
40 | |
SendInit(interp, dispPtr);
|
41 | |
}
|
42 | |
|
43 | |
+ handler = Tk_CreateErrorHandler(dispPtr->display, -1, -1, -1, NULL, NULL);
|
44 | |
+
|
45 | |
regPtr = ckalloc(sizeof(NameRegistry));
|
46 | |
regPtr->dispPtr = dispPtr;
|
47 | |
regPtr->locked = 0;
|
48 | |
@@ -306,8 +309,11 @@
|
49 | |
XDeleteProperty(dispPtr->display,
|
50 | |
RootWindow(dispPtr->display, 0),
|
51 | |
dispPtr->registryProperty);
|
52 | |
+ XSync(dispPtr->display, False);
|
53 | |
}
|
54 | |
|
55 | |
+ Tk_DeleteErrorHandler(handler);
|
56 | |
+
|
57 | |
/*
|
58 | |
* Xlib placed an extra null byte after the end of the property, just to
|
59 | |
* make sure that it is always NULL-terminated. Be sure to include this
|
60 | |
@@ -514,6 +520,11 @@
|
61 | |
NameRegistry *regPtr) /* Pointer to a registry opened with a
|
62 | |
* previous call to RegOpen. */
|
63 | |
{
|
64 | |
+ Tk_ErrorHandler handler;
|
65 | |
+
|
66 | |
+ handler = Tk_CreateErrorHandler(regPtr->dispPtr->display, -1, -1, -1,
|
67 | |
+ NULL, NULL);
|
68 | |
+
|
69 | |
if (regPtr->modified) {
|
70 | |
if (!regPtr->locked && !localData.sendDebug) {
|
71 | |
Tcl_Panic("The name registry was modified without being locked!");
|
72 | |
@@ -540,6 +551,8 @@
|
73 | |
|
74 | |
XFlush(regPtr->dispPtr->display);
|
75 | |
|
76 | |
+ Tk_DeleteErrorHandler(handler);
|
77 | |
+
|
78 | |
if (regPtr->property != NULL) {
|
79 | |
if (regPtr->allocedByX) {
|
80 | |
XFree(regPtr->property);
|
81 | |
@@ -1095,6 +1108,31 @@
|
82 | |
Tcl_DStringAppend(&request, " ", 1);
|
83 | |
Tcl_DStringAppend(&request, Tcl_GetString(objv[i]), -1);
|
84 | |
}
|
85 | |
+
|
86 | |
+ if (!async) {
|
87 | |
+ /*
|
88 | |
+ * Register the fact that we're waiting for a command to complete
|
89 | |
+ * (this is needed by SendEventProc and by AppendErrorProc to pass
|
90 | |
+ * back the command's results). Set up a timeout handler so that
|
91 | |
+ * we can check during long sends to make sure that the destination
|
92 | |
+ * application is still alive.
|
93 | |
+ *
|
94 | |
+ * We prepare the pending struct here in order to catch potential
|
95 | |
+ * early X errors from AppendPropCarefully() due to XSync().
|
96 | |
+ */
|
97 | |
+
|
98 | |
+ pending.serial = localData.sendSerial;
|
99 | |
+ pending.dispPtr = dispPtr;
|
100 | |
+ pending.target = destName;
|
101 | |
+ pending.commWindow = commWindow;
|
102 | |
+ pending.interp = interp;
|
103 | |
+ pending.result = NULL;
|
104 | |
+ pending.errorInfo = NULL;
|
105 | |
+ pending.errorCode = NULL;
|
106 | |
+ pending.gotResponse = 0;
|
107 | |
+ pending.nextPtr = tsdPtr->pendingCommands;
|
108 | |
+ tsdPtr->pendingCommands = &pending;
|
109 | |
+ }
|
110 | |
(void) AppendPropCarefully(dispPtr->display, commWindow,
|
111 | |
dispPtr->commProperty, Tcl_DStringValue(&request),
|
112 | |
Tcl_DStringLength(&request) + 1, (async ? NULL : &pending));
|
113 | |
@@ -1109,26 +1147,6 @@
|
114 | |
}
|
115 | |
|
116 | |
/*
|
117 | |
- * Register the fact that we're waiting for a command to complete (this is
|
118 | |
- * needed by SendEventProc and by AppendErrorProc to pass back the
|
119 | |
- * command's results). Set up a timeout handler so that we can check
|
120 | |
- * during long sends to make sure that the destination application is
|
121 | |
- * still alive.
|
122 | |
- */
|
123 | |
-
|
124 | |
- pending.serial = localData.sendSerial;
|
125 | |
- pending.dispPtr = dispPtr;
|
126 | |
- pending.target = destName;
|
127 | |
- pending.commWindow = commWindow;
|
128 | |
- pending.interp = interp;
|
129 | |
- pending.result = NULL;
|
130 | |
- pending.errorInfo = NULL;
|
131 | |
- pending.errorCode = NULL;
|
132 | |
- pending.gotResponse = 0;
|
133 | |
- pending.nextPtr = tsdPtr->pendingCommands;
|
134 | |
- tsdPtr->pendingCommands = &pending;
|
135 | |
-
|
136 | |
- /*
|
137 | |
* Enter a loop processing X events until the result comes in or the
|
138 | |
* target is declared to be dead. While waiting for a result, look only at
|
139 | |
* send-related events so that the send is synchronous with respect to
|
140 | |
@@ -1951,6 +1969,7 @@
|
141 | |
"bogus", "prop", "serial", NULL
|
142 | |
};
|
143 | |
TkWindow *winPtr = clientData;
|
144 | |
+ Tk_ErrorHandler handler;
|
145 | |
int index;
|
146 | |
|
147 | |
if (objc < 2) {
|
148 | |
@@ -1959,16 +1978,19 @@
|
149 | |
return TCL_ERROR;
|
150 | |
}
|
151 | |
|
152 | |
- if (Tcl_GetIndexFromObjStruct(interp, objv[1], testsendOptions,
|
153 | |
+ if (Tcl_GetIndexFromObjStruct(interp, objv[1], testsendOptions,
|
154 | |
sizeof(char *), "option", 0, &index) != TCL_OK) {
|
155 | |
- return TCL_ERROR;
|
156 | |
- }
|
157 | |
- if (index == TESTSEND_BOGUS) {
|
158 | |
+ return TCL_ERROR;
|
159 | |
+ }
|
160 | |
+ if (index == TESTSEND_BOGUS) {
|
161 | |
+ handler = Tk_CreateErrorHandler(winPtr->dispPtr->display, -1, -1, -1,
|
162 | |
+ NULL, NULL);
|
163 | |
XChangeProperty(winPtr->dispPtr->display,
|
164 | |
RootWindow(winPtr->dispPtr->display, 0),
|
165 | |
winPtr->dispPtr->registryProperty, XA_INTEGER, 32,
|
166 | |
PropModeReplace,
|
167 | |
(unsigned char *) "This is bogus information", 6);
|
168 | |
+ Tk_DeleteErrorHandler(handler);
|
169 | |
} else if (index == TESTSEND_PROP) {
|
170 | |
int result, actualFormat;
|
171 | |
unsigned long length, bytesAfter;
|
172 | |
@@ -2007,7 +2029,10 @@
|
173 | |
XFree(property);
|
174 | |
}
|
175 | |
} else if (Tcl_GetString(objv[4])[0] == 0) {
|
176 | |
+ handler = Tk_CreateErrorHandler(winPtr->dispPtr->display,
|
177 | |
+ -1, -1, -1, NULL, NULL);
|
178 | |
XDeleteProperty(winPtr->dispPtr->display, w, propName);
|
179 | |
+ Tk_DeleteErrorHandler(handler);
|
180 | |
} else {
|
181 | |
Tcl_DString tmp;
|
182 | |
|
183 | |
@@ -2018,10 +2043,12 @@
|
184 | |
*p = 0;
|
185 | |
}
|
186 | |
}
|
187 | |
-
|
188 | |
+ handler = Tk_CreateErrorHandler(winPtr->dispPtr->display,
|
189 | |
+ -1, -1, -1, NULL, NULL);
|
190 | |
XChangeProperty(winPtr->dispPtr->display, w, propName, XA_STRING,
|
191 | |
8, PropModeReplace, (unsigned char*)Tcl_DStringValue(&tmp),
|
192 | |
p-Tcl_DStringValue(&tmp));
|
193 | |
+ Tk_DeleteErrorHandler(handler);
|
194 | |
Tcl_DStringFree(&tmp);
|
195 | |
}
|
196 | |
} else if (index == TESTSEND_SERIAL) {
|