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