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 66static unsigned char *data[4096 * 20]; /* the request data buffer */ 67 68extern ClientRec client_window; 69 70int 71__real_XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client, 72 int len, unsigned char *mask); 73 74int 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 84static void 85request_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 121static void 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 142static void 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 163static void 164request_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 284static void 285test_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 367int 368protocol_xiselectevents_test(void) 369{ 370 init_simple(); 371 372 test_XISelectEvents(); 373 374 return 0; 375} 376