1 /**
2 * Copyright © 2009 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 /* Test relies on assert() */
25 #undef NDEBUG
26
27 #ifdef HAVE_DIX_CONFIG_H
28 #include <dix-config.h>
29 #endif
30
31 /*
32 * Protocol testing for XISelectEvents request.
33 *
34 * Test approach:
35 *
36 * Wrap XISetEventMask to intercept when the server tries to apply the event
37 * mask. Ensure that the mask passed in is equivalent to the one supplied by
38 * the client. Ensure that invalid devices and invalid masks return errors
39 * as appropriate.
40 *
41 * Tests included:
42 * BadValue for num_masks < 0
43 * BadWindow for invalid windows
44 * BadDevice for non-existing devices
45 * BadImplemenation for devices >= 0xFF
46 * BadValue if HierarchyChanged bit is set for devices other than
47 * XIAllDevices
48 * BadValue for invalid mask bits
49 * Sucecss for excessive mask lengths
50 *
51 */
52
53 #include <stdint.h>
54 #include <X11/X.h>
55 #include <X11/Xproto.h>
56 #include <X11/extensions/XI2proto.h>
57 #include "inputstr.h"
58 #include "windowstr.h"
59 #include "extinit.h" /* for XInputExtensionInit */
60 #include "scrnintstr.h"
61 #include "exglobals.h"
62 #include "xiselectev.h"
63
64 #include "protocol-common.h"
65
66 static unsigned char *data[4096 * 20]; /* the request data buffer */
67
68 extern ClientRec client_window;
69
70 int
71 __real_XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
72 int len, unsigned char *mask);
73
74 int
__wrap_XISetEventMask(DeviceIntPtr dev,WindowPtr win,ClientPtr client,int len,unsigned char * mask)75 __wrap_XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
76 int len, unsigned char *mask)
77 {
78 if (!enable_XISetEventMask_wrap)
79 return __real_XISetEventMask(dev, win, client, len, mask);
80
81 return Success;
82 }
83
84 static void
request_XISelectEvent(xXISelectEventsReq * req,int error)85 request_XISelectEvent(xXISelectEventsReq * req, int error)
86 {
87 int i;
88 int rc;
89 ClientRec client;
90 xXIEventMask *mask, *next;
91
92 req->length = (sz_xXISelectEventsReq / 4);
93 mask = (xXIEventMask *) &req[1];
94 for (i = 0; i < req->num_masks; i++) {
95 req->length += sizeof(xXIEventMask) / 4 + mask->mask_len;
96 mask = (xXIEventMask *) ((char *) &mask[1] + mask->mask_len * 4);
97 }
98
99 client = init_client(req->length, req);
100
101 rc = ProcXISelectEvents(&client);
102 assert(rc == error);
103
104 client.swapped = TRUE;
105
106 mask = (xXIEventMask *) &req[1];
107 for (i = 0; i < req->num_masks; i++) {
108 next = (xXIEventMask *) ((char *) &mask[1] + mask->mask_len * 4);
109 swaps(&mask->deviceid);
110 swaps(&mask->mask_len);
111 mask = next;
112 }
113
114 swapl(&req->win);
115 swaps(&req->length);
116 swaps(&req->num_masks);
117 rc = SProcXISelectEvents(&client);
118 assert(rc == error);
119 }
120
121 static void
_set_bit(unsigned char * bits,int bit)122 _set_bit(unsigned char *bits, int bit)
123 {
124 SetBit(bits, bit);
125 if (bit >= XI_TouchBegin && bit <= XI_TouchOwnership) {
126 SetBit(bits, XI_TouchBegin);
127 SetBit(bits, XI_TouchUpdate);
128 SetBit(bits, XI_TouchEnd);
129 }
130 if (bit >= XI_GesturePinchBegin && bit <= XI_GesturePinchEnd) {
131 SetBit(bits, XI_GesturePinchBegin);
132 SetBit(bits, XI_GesturePinchUpdate);
133 SetBit(bits, XI_GesturePinchEnd);
134 }
135 if (bit >= XI_GestureSwipeBegin && bit <= XI_GestureSwipeEnd) {
136 SetBit(bits, XI_GestureSwipeBegin);
137 SetBit(bits, XI_GestureSwipeUpdate);
138 SetBit(bits, XI_GestureSwipeEnd);
139 }
140 }
141
142 static void
_clear_bit(unsigned char * bits,int bit)143 _clear_bit(unsigned char *bits, int bit)
144 {
145 ClearBit(bits, bit);
146 if (bit >= XI_TouchBegin && bit <= XI_TouchOwnership) {
147 ClearBit(bits, XI_TouchBegin);
148 ClearBit(bits, XI_TouchUpdate);
149 ClearBit(bits, XI_TouchEnd);
150 }
151 if (bit >= XI_GesturePinchBegin && bit <= XI_GesturePinchEnd) {
152 ClearBit(bits, XI_GesturePinchBegin);
153 ClearBit(bits, XI_GesturePinchUpdate);
154 ClearBit(bits, XI_GesturePinchEnd);
155 }
156 if (bit >= XI_GestureSwipeBegin && bit <= XI_GestureSwipeEnd) {
157 ClearBit(bits, XI_GestureSwipeBegin);
158 ClearBit(bits, XI_GestureSwipeUpdate);
159 ClearBit(bits, XI_GestureSwipeEnd);
160 }
161 }
162
163 static void
request_XISelectEvents_masks(xXISelectEventsReq * req)164 request_XISelectEvents_masks(xXISelectEventsReq * req)
165 {
166 int i, j;
167 xXIEventMask *mask;
168 int nmasks = XI2MASKSIZE;
169 unsigned char *bits;
170
171 mask = (xXIEventMask *) &req[1];
172 req->win = ROOT_WINDOW_ID;
173
174 /* if a clients submits more than 100 masks, consider it insane and untested */
175 for (i = 1; i <= 1000; i++) {
176 req->num_masks = i;
177 mask->deviceid = XIAllDevices;
178
179 /* Test 0:
180 * mask_len is 0 -> Success
181 */
182 mask->mask_len = 0;
183 request_XISelectEvent(req, Success);
184
185 /* Test 1:
186 * mask may be larger than needed for XI2LASTEVENT.
187 * Test setting each valid mask bit, while leaving unneeded bits 0.
188 * -> Success
189 */
190 bits = (unsigned char *) &mask[1];
191 mask->mask_len = (nmasks + 3) / 4 * 10;
192 memset(bits, 0, mask->mask_len * 4);
193 for (j = 0; j <= XI2LASTEVENT; j++) {
194 _set_bit(bits, j);
195 request_XISelectEvent(req, Success);
196 _clear_bit(bits, j);
197 }
198
199 /* Test 2:
200 * mask may be larger than needed for XI2LASTEVENT.
201 * Test setting all valid mask bits, while leaving unneeded bits 0.
202 * -> Success
203 */
204 bits = (unsigned char *) &mask[1];
205 mask->mask_len = (nmasks + 3) / 4 * 10;
206 memset(bits, 0, mask->mask_len * 4);
207
208 for (j = 0; j <= XI2LASTEVENT; j++) {
209 _set_bit(bits, j);
210 request_XISelectEvent(req, Success);
211 }
212
213 /* Test 3:
214 * mask is larger than needed for XI2LASTEVENT. If any unneeded bit
215 * is set -> BadValue
216 */
217 bits = (unsigned char *) &mask[1];
218 mask->mask_len = (nmasks + 3) / 4 * 10;
219 memset(bits, 0, mask->mask_len * 4);
220
221 for (j = XI2LASTEVENT + 1; j < mask->mask_len * 4; j++) {
222 _set_bit(bits, j);
223 request_XISelectEvent(req, BadValue);
224 _clear_bit(bits, j);
225 }
226
227 /* Test 4:
228 * Mask len is a sensible length, only valid bits are set -> Success
229 */
230 bits = (unsigned char *) &mask[1];
231 mask->mask_len = (nmasks + 3) / 4;
232 memset(bits, 0, mask->mask_len * 4);
233 for (j = 0; j <= XI2LASTEVENT; j++) {
234 _set_bit(bits, j);
235 request_XISelectEvent(req, Success);
236 }
237
238 /* Test 5:
239 * Mask len is 1 and XI_GestureSwipeEnd is set outside the mask.
240 * That bit should be ignored -> Success
241 */
242 bits = (unsigned char *) &mask[1];
243 mask->mask_len = 1;
244 memset(bits, 0, 5);
245 SetBit(bits, XI_ButtonPress); // does not matter which one
246 SetBit(bits, XI_GestureSwipeEnd);
247 request_XISelectEvent(req, Success);
248
249 /* Test 6:
250 * HierarchyChanged bit is BadValue for devices other than
251 * XIAllDevices
252 */
253 bits = (unsigned char *) &mask[1];
254 mask->mask_len = (nmasks + 3) / 4;
255 memset(bits, 0, mask->mask_len * 4);
256 SetBit(bits, XI_HierarchyChanged);
257 mask->deviceid = XIAllDevices;
258 request_XISelectEvent(req, Success);
259 for (j = 1; j < devices.num_devices; j++) {
260 mask->deviceid = j;
261 request_XISelectEvent(req, BadValue);
262 }
263
264 /* Test 7:
265 * All bits set minus hierarchy changed bit -> Success
266 */
267 bits = (unsigned char *) &mask[1];
268 mask->mask_len = (nmasks + 3) / 4;
269 memset(bits, 0, mask->mask_len * 4);
270 for (j = 0; j <= XI2LASTEVENT; j++)
271 _set_bit(bits, j);
272 _clear_bit(bits, XI_HierarchyChanged);
273 for (j = 1; j < 6; j++) {
274 mask->deviceid = j;
275 request_XISelectEvent(req, Success);
276 }
277
278 mask =
279 (xXIEventMask *) ((char *) mask + sizeof(xXIEventMask) +
280 mask->mask_len * 4);
281 }
282 }
283
284 static void
test_XISelectEvents(void)285 test_XISelectEvents(void)
286 {
287 int i;
288 xXIEventMask *mask;
289 xXISelectEventsReq *req;
290
291 req = (xXISelectEventsReq *) data;
292
293 request_init(req, XISelectEvents);
294
295 printf("Testing for BadValue on zero-length masks\n");
296 /* zero masks are BadValue, regardless of the window */
297 req->num_masks = 0;
298
299 req->win = None;
300 request_XISelectEvent(req, BadValue);
301
302 req->win = ROOT_WINDOW_ID;
303 request_XISelectEvent(req, BadValue);
304
305 req->win = CLIENT_WINDOW_ID;
306 request_XISelectEvent(req, BadValue);
307
308 printf("Testing for BadWindow.\n");
309 /* None window is BadWindow, regardless of the masks.
310 * We don't actually need to set the masks here, BadWindow must occur
311 * before checking the masks.
312 */
313 req->win = None;
314 req->num_masks = 1;
315 request_XISelectEvent(req, BadWindow);
316
317 req->num_masks = 2;
318 request_XISelectEvent(req, BadWindow);
319
320 req->num_masks = 0xFF;
321 request_XISelectEvent(req, BadWindow);
322
323 /* request size is 3, so 0xFFFC is the highest num_mask that doesn't
324 * overflow req->length */
325 req->num_masks = 0xFFFC;
326 request_XISelectEvent(req, BadWindow);
327
328 printf("Triggering num_masks/length overflow\n");
329 req->win = ROOT_WINDOW_ID;
330 /* Integer overflow - req->length can't hold that much */
331 req->num_masks = 0xFFFF;
332 request_XISelectEvent(req, BadLength);
333
334 req->win = ROOT_WINDOW_ID;
335 req->num_masks = 1;
336
337 printf("Triggering bogus mask length error\n");
338 mask = (xXIEventMask *) &req[1];
339 mask->deviceid = 0;
340 mask->mask_len = 0xFFFF;
341 request_XISelectEvent(req, BadLength);
342
343 /* testing various device ids */
344 printf("Testing existing device ids.\n");
345 for (i = 0; i < 6; i++) {
346 mask = (xXIEventMask *) &req[1];
347 mask->deviceid = i;
348 mask->mask_len = 1;
349 req->win = ROOT_WINDOW_ID;
350 req->num_masks = 1;
351 request_XISelectEvent(req, Success);
352 }
353
354 printf("Testing non-existing device ids.\n");
355 for (i = 6; i <= 0xFFFF; i++) {
356 req->win = ROOT_WINDOW_ID;
357 req->num_masks = 1;
358 mask = (xXIEventMask *) &req[1];
359 mask->deviceid = i;
360 mask->mask_len = 1;
361 request_XISelectEvent(req, BadDevice);
362 }
363
364 request_XISelectEvents_masks(req);
365 }
366
367 int
protocol_xiselectevents_test(void)368 protocol_xiselectevents_test(void)
369 {
370 init_simple();
371
372 test_XISelectEvents();
373
374 return 0;
375 }
376