protocol-xiselectevents.c revision 35c4bbdf
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#ifdef HAVE_DIX_CONFIG_H 25#include <dix-config.h> 26#endif 27 28/* 29 * Protocol testing for XISelectEvents request. 30 * 31 * Test approach: 32 * 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 36 * as appropriate. 37 * 38 * Tests included: 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 44 * XIAllDevices 45 * BadValue for invalid mask bits 46 * Sucecss for excessive mask lengths 47 * 48 */ 49 50#include <stdint.h> 51#include <X11/X.h> 52#include <X11/Xproto.h> 53#include <X11/extensions/XI2proto.h> 54#include "inputstr.h" 55#include "windowstr.h" 56#include "extinit.h" /* for XInputExtensionInit */ 57#include "scrnintstr.h" 58#include "exglobals.h" 59#include "xiselectev.h" 60 61#include "protocol-common.h" 62 63static unsigned char *data[4096 * 20]; /* the request data buffer */ 64 65int 66__wrap_XISetEventMask(DeviceIntPtr dev, WindowPtr win, int len, 67 unsigned char *mask) 68{ 69 return Success; 70} 71 72/* dixLookupWindow requires a lot of setup not necessary for this test. 73 * Simple wrapper that returns either one of the fake root window or the 74 * fake client window. If the requested ID is neither of those wanted, 75 * return whatever the real dixLookupWindow does. 76 */ 77int 78__wrap_dixLookupWindow(WindowPtr *win, XID id, ClientPtr client, Mask access) 79{ 80 if (id == root.drawable.id) { 81 *win = &root; 82 return Success; 83 } 84 else if (id == window.drawable.id) { 85 *win = &window; 86 return Success; 87 } 88 89 return __real_dixLookupWindow(win, id, client, access); 90} 91 92static void 93request_XISelectEvent(xXISelectEventsReq * req, int error) 94{ 95 int i; 96 int rc; 97 ClientRec client; 98 xXIEventMask *mask, *next; 99 100 req->length = (sz_xXISelectEventsReq / 4); 101 mask = (xXIEventMask *) &req[1]; 102 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); 105 } 106 107 client = init_client(req->length, req); 108 109 rc = ProcXISelectEvents(&client); 110 assert(rc == error); 111 112 client.swapped = TRUE; 113 114 mask = (xXIEventMask *) &req[1]; 115 for (i = 0; i < req->num_masks; i++) { 116 next = (xXIEventMask *) ((char *) &mask[1] + mask->mask_len * 4); 117 swaps(&mask->deviceid); 118 swaps(&mask->mask_len); 119 mask = next; 120 } 121 122 swapl(&req->win); 123 swaps(&req->length); 124 swaps(&req->num_masks); 125 rc = SProcXISelectEvents(&client); 126 assert(rc == error); 127} 128 129static void 130_set_bit(unsigned char *bits, int bit) 131{ 132 SetBit(bits, bit); 133 if (bit >= XI_TouchBegin && bit <= XI_TouchOwnership) { 134 SetBit(bits, XI_TouchBegin); 135 SetBit(bits, XI_TouchUpdate); 136 SetBit(bits, XI_TouchEnd); 137 } 138} 139 140static void 141_clear_bit(unsigned char *bits, int bit) 142{ 143 ClearBit(bits, bit); 144 if (bit >= XI_TouchBegin && bit <= XI_TouchOwnership) { 145 ClearBit(bits, XI_TouchBegin); 146 ClearBit(bits, XI_TouchUpdate); 147 ClearBit(bits, XI_TouchEnd); 148 } 149} 150 151static void 152request_XISelectEvents_masks(xXISelectEventsReq * req) 153{ 154 int i, j; 155 xXIEventMask *mask; 156 int nmasks = (XI2LASTEVENT + 7) / 8; 157 unsigned char *bits; 158 159 mask = (xXIEventMask *) &req[1]; 160 req->win = ROOT_WINDOW_ID; 161 162 /* if a clients submits more than 100 masks, consider it insane and untested */ 163 for (i = 1; i <= 1000; i++) { 164 req->num_masks = i; 165 mask->deviceid = XIAllDevices; 166 167 /* Test 0: 168 * mask_len is 0 -> Success 169 */ 170 mask->mask_len = 0; 171 request_XISelectEvent(req, Success); 172 173 /* Test 1: 174 * mask may be larger than needed for XI2LASTEVENT. 175 * Test setting each valid mask bit, while leaving unneeded bits 0. 176 * -> Success 177 */ 178 bits = (unsigned char *) &mask[1]; 179 mask->mask_len = (nmasks + 3) / 4 * 10; 180 memset(bits, 0, mask->mask_len * 4); 181 for (j = 0; j <= XI2LASTEVENT; j++) { 182 _set_bit(bits, j); 183 request_XISelectEvent(req, Success); 184 _clear_bit(bits, j); 185 } 186 187 /* Test 2: 188 * mask may be larger than needed for XI2LASTEVENT. 189 * Test setting all valid mask bits, while leaving unneeded bits 0. 190 * -> Success 191 */ 192 bits = (unsigned char *) &mask[1]; 193 mask->mask_len = (nmasks + 3) / 4 * 10; 194 memset(bits, 0, mask->mask_len * 4); 195 196 for (j = 0; j <= XI2LASTEVENT; j++) { 197 _set_bit(bits, j); 198 request_XISelectEvent(req, Success); 199 } 200 201 /* Test 3: 202 * mask is larger than needed for XI2LASTEVENT. If any unneeded bit 203 * is set -> BadValue 204 */ 205 bits = (unsigned char *) &mask[1]; 206 mask->mask_len = (nmasks + 3) / 4 * 10; 207 memset(bits, 0, mask->mask_len * 4); 208 209 for (j = XI2LASTEVENT + 1; j < mask->mask_len * 4; j++) { 210 _set_bit(bits, j); 211 request_XISelectEvent(req, BadValue); 212 _clear_bit(bits, j); 213 } 214 215 /* Test 4: 216 * Mask len is a sensible length, only valid bits are set -> Success 217 */ 218 bits = (unsigned char *) &mask[1]; 219 mask->mask_len = (nmasks + 3) / 4; 220 memset(bits, 0, mask->mask_len * 4); 221 for (j = 0; j <= XI2LASTEVENT; j++) { 222 _set_bit(bits, j); 223 request_XISelectEvent(req, Success); 224 } 225 226 /* Test 5: 227 * HierarchyChanged bit is BadValue for devices other than 228 * XIAllDevices 229 */ 230 bits = (unsigned char *) &mask[1]; 231 mask->mask_len = (nmasks + 3) / 4; 232 memset(bits, 0, mask->mask_len * 4); 233 SetBit(bits, XI_HierarchyChanged); 234 mask->deviceid = XIAllDevices; 235 request_XISelectEvent(req, Success); 236 for (j = 1; j < devices.num_devices; j++) { 237 mask->deviceid = j; 238 request_XISelectEvent(req, BadValue); 239 } 240 241 /* Test 6: 242 * All bits set minus hierarchy changed bit -> Success 243 */ 244 bits = (unsigned char *) &mask[1]; 245 mask->mask_len = (nmasks + 3) / 4; 246 memset(bits, 0, mask->mask_len * 4); 247 for (j = 0; j <= XI2LASTEVENT; j++) 248 _set_bit(bits, j); 249 _clear_bit(bits, XI_HierarchyChanged); 250 for (j = 1; j < 6; j++) { 251 mask->deviceid = j; 252 request_XISelectEvent(req, Success); 253 } 254 255 mask = 256 (xXIEventMask *) ((char *) mask + sizeof(xXIEventMask) + 257 mask->mask_len * 4); 258 } 259} 260 261static void 262test_XISelectEvents(void) 263{ 264 int i; 265 xXIEventMask *mask; 266 xXISelectEventsReq *req; 267 268 req = (xXISelectEventsReq *) data; 269 270 request_init(req, XISelectEvents); 271 272 printf("Testing for BadValue on zero-length masks\n"); 273 /* zero masks are BadValue, regardless of the window */ 274 req->num_masks = 0; 275 276 req->win = None; 277 request_XISelectEvent(req, BadValue); 278 279 req->win = ROOT_WINDOW_ID; 280 request_XISelectEvent(req, BadValue); 281 282 req->win = CLIENT_WINDOW_ID; 283 request_XISelectEvent(req, BadValue); 284 285 printf("Testing for BadWindow.\n"); 286 /* None window is BadWindow, regardless of the masks. 287 * We don't actually need to set the masks here, BadWindow must occur 288 * before checking the masks. 289 */ 290 req->win = None; 291 req->num_masks = 1; 292 request_XISelectEvent(req, BadWindow); 293 294 req->num_masks = 2; 295 request_XISelectEvent(req, BadWindow); 296 297 req->num_masks = 0xFF; 298 request_XISelectEvent(req, BadWindow); 299 300 /* request size is 3, so 0xFFFC is the highest num_mask that doesn't 301 * overflow req->length */ 302 req->num_masks = 0xFFFC; 303 request_XISelectEvent(req, BadWindow); 304 305 printf("Triggering num_masks/length overflow\n"); 306 req->win = ROOT_WINDOW_ID; 307 /* Integer overflow - req->length can't hold that much */ 308 req->num_masks = 0xFFFF; 309 request_XISelectEvent(req, BadLength); 310 311 req->win = ROOT_WINDOW_ID; 312 req->num_masks = 1; 313 314 printf("Triggering bogus mask length error\n"); 315 mask = (xXIEventMask *) &req[1]; 316 mask->deviceid = 0; 317 mask->mask_len = 0xFFFF; 318 request_XISelectEvent(req, BadLength); 319 320 /* testing various device ids */ 321 printf("Testing existing device ids.\n"); 322 for (i = 0; i < 6; i++) { 323 mask = (xXIEventMask *) &req[1]; 324 mask->deviceid = i; 325 mask->mask_len = 1; 326 req->win = ROOT_WINDOW_ID; 327 req->num_masks = 1; 328 request_XISelectEvent(req, Success); 329 } 330 331 printf("Testing non-existing device ids.\n"); 332 for (i = 6; i <= 0xFFFF; i++) { 333 req->win = ROOT_WINDOW_ID; 334 req->num_masks = 1; 335 mask = (xXIEventMask *) &req[1]; 336 mask->deviceid = i; 337 mask->mask_len = 1; 338 request_XISelectEvent(req, BadDevice); 339 } 340 341 request_XISelectEvents_masks(req); 342} 343 344int 345main(int argc, char **argv) 346{ 347 init_simple(); 348 349 test_XISelectEvents(); 350 351 return 0; 352} 353