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