2
* Copyright © 2009 Red Hat, Inc.
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:
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
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.
24
#ifdef HAVE_DIX_CONFIG_H
25
#include <dix-config.h>
29
* Protocol testing for XISelectEvents request.
33
* Wrap XISetEventMask to intercept when the server tries to apply the event
34
* mask. Ensure that the mask passed in is equivalent to the one supplied by
35
* the client. Ensure that invalid devices and invalid masks return errors
39
* BadValue for num_masks < 0
40
* BadWindow for invalid windows
41
* BadDevice for non-existing devices
42
* BadImplemenation for devices >= 0xFF
43
* BadValue if HierarchyChanged bit is set for devices other than
45
* BadValue for invalid mask bits
46
* Sucecss for excessive mask lengths
52
#include <X11/Xproto.h>
53
#include <X11/extensions/XI2proto.h>
55
#include "windowstr.h"
56
#include "extinit.h" /* for XInputExtensionInit */
57
#include "scrnintstr.h"
58
#include "xiselectev.h"
60
#include "protocol-common.h"
63
static unsigned char *data[4096 * 20]; /* the request data buffer */
65
int __wrap_XISetEventMask(DeviceIntPtr dev, WindowPtr win, int len, unsigned char* mask)
70
/* dixLookupWindow requires a lot of setup not necessary for this test.
71
* Simple wrapper that returns either one of the fake root window or the
72
* fake client window. If the requested ID is neither of those wanted,
73
* return whatever the real dixLookupWindow does.
75
int __wrap_dixLookupWindow(WindowPtr *win, XID id, ClientPtr client, Mask access)
77
if (id == root.drawable.id)
81
} else if (id == window.drawable.id)
87
return __real_dixLookupWindow(win, id, client, access);
91
static void request_XISelectEvent(xXISelectEventsReq *req, int error)
97
xXIEventMask *mask, *next;
99
req->length = (sz_xXISelectEventsReq/4);
100
mask = (xXIEventMask*)&req[1];
101
for (i = 0; i < req->num_masks; i++)
103
req->length += sizeof(xXIEventMask)/4 + mask->mask_len;
104
mask = (xXIEventMask*)((char*)&mask[1] + mask->mask_len * 4);
107
client = init_client(req->length, req);
109
rc = ProcXISelectEvents(&client);
110
g_assert(rc == error);
112
client.swapped = TRUE;
114
mask = (xXIEventMask*)&req[1];
115
for (i = 0; i < req->num_masks; i++)
117
next = (xXIEventMask*)((char*)&mask[1] + mask->mask_len * 4);
118
swaps(&mask->deviceid, n);
119
swaps(&mask->mask_len, n);
124
swaps(&req->length, n);
125
swaps(&req->num_masks, n);
126
rc = SProcXISelectEvents(&client);
127
g_assert(rc == error);
130
static void request_XISelectEvents_masks(xXISelectEventsReq *req)
134
int nmasks = (XI_LASTEVENT + 7)/8;
137
mask = (xXIEventMask*)&req[1];
138
req->win = ROOT_WINDOW_ID;
140
/* if a clients submits more than 100 masks, consider it insane and untested */
141
for (i = 1; i <= 1000; i++)
144
mask->deviceid = XIAllDevices;
147
* mask_len is 0 -> Success
150
request_XISelectEvent(req, Success);
153
* mask may be larger than needed for XI_LASTEVENT.
154
* Test setting each valid mask bit, while leaving unneeded bits 0.
157
bits = (unsigned char*)&mask[1];
158
mask->mask_len = (nmasks + 3)/4 * 10;
159
memset(bits, 0, mask->mask_len * 4);
160
for (j = 0; j <= XI_LASTEVENT; j++)
163
request_XISelectEvent(req, Success);
168
* mask may be larger than needed for XI_LASTEVENT.
169
* Test setting all valid mask bits, while leaving unneeded bits 0.
172
bits = (unsigned char*)&mask[1];
173
mask->mask_len = (nmasks + 3)/4 * 10;
174
memset(bits, 0, mask->mask_len * 4);
176
for (j = 0; j <= XI_LASTEVENT; j++)
179
request_XISelectEvent(req, Success);
183
* mask is larger than needed for XI_LASTEVENT. If any unneeded bit
186
bits = (unsigned char*)&mask[1];
187
mask->mask_len = (nmasks + 3)/4 * 10;
188
memset(bits, 0, mask->mask_len * 4);
190
for (j = XI_LASTEVENT + 1; j < mask->mask_len * 4; j++)
193
request_XISelectEvent(req, BadValue);
198
* Mask len is a sensible length, only valid bits are set -> Success
200
bits = (unsigned char*)&mask[1];
201
mask->mask_len = (nmasks + 3)/4;
202
memset(bits, 0, mask->mask_len * 4);
203
for (j = 0; j <= XI_LASTEVENT; j++)
206
request_XISelectEvent(req, Success);
210
* HierarchyChanged bit is BadValue for devices other than
213
bits = (unsigned char*)&mask[1];
214
mask->mask_len = (nmasks + 3)/4;
215
memset(bits, 0, mask->mask_len * 4);
216
SetBit(bits, XI_HierarchyChanged);
217
mask->deviceid = XIAllDevices;
218
request_XISelectEvent(req, Success);
219
for (j = 1; j < devices.num_devices; j++)
222
request_XISelectEvent(req, BadValue);
226
* All bits set minus hierarchy changed bit -> Success
228
bits = (unsigned char*)&mask[1];
229
mask->mask_len = (nmasks + 3)/4;
230
memset(bits, 0, mask->mask_len * 4);
231
for (j = 0; j <= XI_LASTEVENT; j++)
233
ClearBit(bits, XI_HierarchyChanged);
234
for (j = 1; j < 6; j++)
237
request_XISelectEvent(req, Success);
240
mask = (xXIEventMask*)((char*)mask + sizeof(xXIEventMask) + mask->mask_len * 4);
244
static void test_XISelectEvents(void)
248
xXISelectEventsReq *req;
249
req = (xXISelectEventsReq*)data;
251
request_init(req, XISelectEvents);
253
g_test_message("Testing for BadValue on zero-length masks");
254
/* zero masks are BadValue, regardless of the window */
258
request_XISelectEvent(req, BadValue);
260
req->win = ROOT_WINDOW_ID;
261
request_XISelectEvent(req, BadValue);
263
req->win = CLIENT_WINDOW_ID;
264
request_XISelectEvent(req, BadValue);
266
g_test_message("Testing for BadWindow.");
267
/* None window is BadWindow, regardless of the masks.
268
* We don't actually need to set the masks here, BadWindow must occur
269
* before checking the masks.
273
request_XISelectEvent(req, BadWindow);
276
request_XISelectEvent(req, BadWindow);
278
req->num_masks = 0xFF;
279
request_XISelectEvent(req, BadWindow);
281
/* request size is 3, so 0xFFFC is the highest num_mask that doesn't
282
* overflow req->length */
283
req->num_masks = 0xFFFC;
284
request_XISelectEvent(req, BadWindow);
286
g_test_message("Triggering num_masks/length overflow");
287
req->win = ROOT_WINDOW_ID;
288
/* Integer overflow - req->length can't hold that much */
289
req->num_masks = 0xFFFF;
290
request_XISelectEvent(req, BadLength);
292
req->win = ROOT_WINDOW_ID;
295
g_test_message("Triggering bogus mask length error");
296
mask = (xXIEventMask*)&req[1];
298
mask->mask_len = 0xFFFF;
299
request_XISelectEvent(req, BadLength);
301
/* testing various device ids */
302
g_test_message("Testing existing device ids.");
303
for (i = 0; i < 6; i++)
305
mask = (xXIEventMask*)&req[1];
308
req->win = ROOT_WINDOW_ID;
310
request_XISelectEvent(req, Success);
313
g_test_message("Testing non-existing device ids.");
314
for (i = 6; i <= 0xFFFF; i++)
316
req->win = ROOT_WINDOW_ID;
318
mask = (xXIEventMask*)&req[1];
321
request_XISelectEvent(req, BadDevice);
324
request_XISelectEvents_masks(req);
327
int main(int argc, char** argv)
329
g_test_init(&argc, &argv,NULL);
330
g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
334
g_test_add_func("/xi2/protocol/XISelectEvents", test_XISelectEvents);