protocol-xiselectevents.c revision 5a7dfde8
16747b715Smrg/** 26747b715Smrg * Copyright © 2009 Red Hat, Inc. 36747b715Smrg * 46747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a 56747b715Smrg * copy of this software and associated documentation files (the "Software"), 66747b715Smrg * to deal in the Software without restriction, including without limitation 76747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 86747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the 96747b715Smrg * Software is furnished to do so, subject to the following conditions: 106747b715Smrg * 116747b715Smrg * The above copyright notice and this permission notice (including the next 126747b715Smrg * paragraph) shall be included in all copies or substantial portions of the 136747b715Smrg * Software. 146747b715Smrg * 156747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 166747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 176747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 186747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 196747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 206747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 216747b715Smrg * DEALINGS IN THE SOFTWARE. 226747b715Smrg */ 236747b715Smrg 246747b715Smrg#ifdef HAVE_DIX_CONFIG_H 256747b715Smrg#include <dix-config.h> 266747b715Smrg#endif 276747b715Smrg 286747b715Smrg/* 296747b715Smrg * Protocol testing for XISelectEvents request. 306747b715Smrg * 316747b715Smrg * Test approach: 326747b715Smrg * 336747b715Smrg * Wrap XISetEventMask to intercept when the server tries to apply the event 346747b715Smrg * mask. Ensure that the mask passed in is equivalent to the one supplied by 356747b715Smrg * the client. Ensure that invalid devices and invalid masks return errors 366747b715Smrg * as appropriate. 376747b715Smrg * 386747b715Smrg * Tests included: 396747b715Smrg * BadValue for num_masks < 0 406747b715Smrg * BadWindow for invalid windows 416747b715Smrg * BadDevice for non-existing devices 426747b715Smrg * BadImplemenation for devices >= 0xFF 436747b715Smrg * BadValue if HierarchyChanged bit is set for devices other than 446747b715Smrg * XIAllDevices 456747b715Smrg * BadValue for invalid mask bits 466747b715Smrg * Sucecss for excessive mask lengths 476747b715Smrg * 486747b715Smrg */ 496747b715Smrg 506747b715Smrg#include <stdint.h> 516747b715Smrg#include <X11/X.h> 526747b715Smrg#include <X11/Xproto.h> 536747b715Smrg#include <X11/extensions/XI2proto.h> 546747b715Smrg#include "inputstr.h" 556747b715Smrg#include "windowstr.h" 5635c4bbdfSmrg#include "extinit.h" /* for XInputExtensionInit */ 576747b715Smrg#include "scrnintstr.h" 5835c4bbdfSmrg#include "exglobals.h" 596747b715Smrg#include "xiselectev.h" 606747b715Smrg 616747b715Smrg#include "protocol-common.h" 626747b715Smrg 6335c4bbdfSmrgstatic unsigned char *data[4096 * 20]; /* the request data buffer */ 646747b715Smrg 655a7dfde8Smrgextern ClientRec client_window; 661b5d61b8Smrg 6735c4bbdfSmrgint 681b5d61b8Smrg__real_XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client, 691b5d61b8Smrg int len, unsigned char *mask); 706747b715Smrg 7135c4bbdfSmrgint 721b5d61b8Smrg__wrap_XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client, 731b5d61b8Smrg int len, unsigned char *mask) 746747b715Smrg{ 751b5d61b8Smrg if (!enable_XISetEventMask_wrap) 761b5d61b8Smrg return __real_XISetEventMask(dev, win, client, len, mask); 776747b715Smrg 781b5d61b8Smrg return Success; 796747b715Smrg} 806747b715Smrg 8135c4bbdfSmrgstatic void 8235c4bbdfSmrgrequest_XISelectEvent(xXISelectEventsReq * req, int error) 836747b715Smrg{ 846747b715Smrg int i; 856747b715Smrg int rc; 866747b715Smrg ClientRec client; 876747b715Smrg xXIEventMask *mask, *next; 886747b715Smrg 8935c4bbdfSmrg req->length = (sz_xXISelectEventsReq / 4); 9035c4bbdfSmrg mask = (xXIEventMask *) &req[1]; 9135c4bbdfSmrg for (i = 0; i < req->num_masks; i++) { 9235c4bbdfSmrg req->length += sizeof(xXIEventMask) / 4 + mask->mask_len; 9335c4bbdfSmrg mask = (xXIEventMask *) ((char *) &mask[1] + mask->mask_len * 4); 946747b715Smrg } 956747b715Smrg 966747b715Smrg client = init_client(req->length, req); 976747b715Smrg 986747b715Smrg rc = ProcXISelectEvents(&client); 9935c4bbdfSmrg assert(rc == error); 1006747b715Smrg 1016747b715Smrg client.swapped = TRUE; 1026747b715Smrg 10335c4bbdfSmrg mask = (xXIEventMask *) &req[1]; 10435c4bbdfSmrg for (i = 0; i < req->num_masks; i++) { 10535c4bbdfSmrg next = (xXIEventMask *) ((char *) &mask[1] + mask->mask_len * 4); 10635c4bbdfSmrg swaps(&mask->deviceid); 10735c4bbdfSmrg swaps(&mask->mask_len); 1086747b715Smrg mask = next; 1096747b715Smrg } 1106747b715Smrg 11135c4bbdfSmrg swapl(&req->win); 11235c4bbdfSmrg swaps(&req->length); 11335c4bbdfSmrg swaps(&req->num_masks); 1146747b715Smrg rc = SProcXISelectEvents(&client); 11535c4bbdfSmrg assert(rc == error); 11635c4bbdfSmrg} 11735c4bbdfSmrg 11835c4bbdfSmrgstatic void 11935c4bbdfSmrg_set_bit(unsigned char *bits, int bit) 12035c4bbdfSmrg{ 12135c4bbdfSmrg SetBit(bits, bit); 12235c4bbdfSmrg if (bit >= XI_TouchBegin && bit <= XI_TouchOwnership) { 12335c4bbdfSmrg SetBit(bits, XI_TouchBegin); 12435c4bbdfSmrg SetBit(bits, XI_TouchUpdate); 12535c4bbdfSmrg SetBit(bits, XI_TouchEnd); 12635c4bbdfSmrg } 12735c4bbdfSmrg} 12835c4bbdfSmrg 12935c4bbdfSmrgstatic void 13035c4bbdfSmrg_clear_bit(unsigned char *bits, int bit) 13135c4bbdfSmrg{ 13235c4bbdfSmrg ClearBit(bits, bit); 13335c4bbdfSmrg if (bit >= XI_TouchBegin && bit <= XI_TouchOwnership) { 13435c4bbdfSmrg ClearBit(bits, XI_TouchBegin); 13535c4bbdfSmrg ClearBit(bits, XI_TouchUpdate); 13635c4bbdfSmrg ClearBit(bits, XI_TouchEnd); 13735c4bbdfSmrg } 1386747b715Smrg} 1396747b715Smrg 14035c4bbdfSmrgstatic void 14135c4bbdfSmrgrequest_XISelectEvents_masks(xXISelectEventsReq * req) 1426747b715Smrg{ 1436747b715Smrg int i, j; 1446747b715Smrg xXIEventMask *mask; 14535c4bbdfSmrg int nmasks = (XI2LASTEVENT + 7) / 8; 1466747b715Smrg unsigned char *bits; 1476747b715Smrg 14835c4bbdfSmrg mask = (xXIEventMask *) &req[1]; 1496747b715Smrg req->win = ROOT_WINDOW_ID; 1506747b715Smrg 1516747b715Smrg /* if a clients submits more than 100 masks, consider it insane and untested */ 15235c4bbdfSmrg for (i = 1; i <= 1000; i++) { 1536747b715Smrg req->num_masks = i; 1546747b715Smrg mask->deviceid = XIAllDevices; 1556747b715Smrg 1566747b715Smrg /* Test 0: 1576747b715Smrg * mask_len is 0 -> Success 1586747b715Smrg */ 1596747b715Smrg mask->mask_len = 0; 1606747b715Smrg request_XISelectEvent(req, Success); 1616747b715Smrg 1626747b715Smrg /* Test 1: 1639ace9065Smrg * mask may be larger than needed for XI2LASTEVENT. 1646747b715Smrg * Test setting each valid mask bit, while leaving unneeded bits 0. 1656747b715Smrg * -> Success 1666747b715Smrg */ 16735c4bbdfSmrg bits = (unsigned char *) &mask[1]; 16835c4bbdfSmrg mask->mask_len = (nmasks + 3) / 4 * 10; 1696747b715Smrg memset(bits, 0, mask->mask_len * 4); 17035c4bbdfSmrg for (j = 0; j <= XI2LASTEVENT; j++) { 17135c4bbdfSmrg _set_bit(bits, j); 1726747b715Smrg request_XISelectEvent(req, Success); 17335c4bbdfSmrg _clear_bit(bits, j); 1746747b715Smrg } 1756747b715Smrg 1766747b715Smrg /* Test 2: 1779ace9065Smrg * mask may be larger than needed for XI2LASTEVENT. 1786747b715Smrg * Test setting all valid mask bits, while leaving unneeded bits 0. 1796747b715Smrg * -> Success 1806747b715Smrg */ 18135c4bbdfSmrg bits = (unsigned char *) &mask[1]; 18235c4bbdfSmrg mask->mask_len = (nmasks + 3) / 4 * 10; 1836747b715Smrg memset(bits, 0, mask->mask_len * 4); 1846747b715Smrg 18535c4bbdfSmrg for (j = 0; j <= XI2LASTEVENT; j++) { 18635c4bbdfSmrg _set_bit(bits, j); 1876747b715Smrg request_XISelectEvent(req, Success); 1886747b715Smrg } 1896747b715Smrg 1906747b715Smrg /* Test 3: 1919ace9065Smrg * mask is larger than needed for XI2LASTEVENT. If any unneeded bit 1926747b715Smrg * is set -> BadValue 1936747b715Smrg */ 19435c4bbdfSmrg bits = (unsigned char *) &mask[1]; 19535c4bbdfSmrg mask->mask_len = (nmasks + 3) / 4 * 10; 1966747b715Smrg memset(bits, 0, mask->mask_len * 4); 1976747b715Smrg 19835c4bbdfSmrg for (j = XI2LASTEVENT + 1; j < mask->mask_len * 4; j++) { 19935c4bbdfSmrg _set_bit(bits, j); 2006747b715Smrg request_XISelectEvent(req, BadValue); 20135c4bbdfSmrg _clear_bit(bits, j); 2026747b715Smrg } 2036747b715Smrg 2046747b715Smrg /* Test 4: 2056747b715Smrg * Mask len is a sensible length, only valid bits are set -> Success 2066747b715Smrg */ 20735c4bbdfSmrg bits = (unsigned char *) &mask[1]; 20835c4bbdfSmrg mask->mask_len = (nmasks + 3) / 4; 2096747b715Smrg memset(bits, 0, mask->mask_len * 4); 21035c4bbdfSmrg for (j = 0; j <= XI2LASTEVENT; j++) { 21135c4bbdfSmrg _set_bit(bits, j); 2126747b715Smrg request_XISelectEvent(req, Success); 2136747b715Smrg } 2146747b715Smrg 2156747b715Smrg /* Test 5: 2166747b715Smrg * HierarchyChanged bit is BadValue for devices other than 2176747b715Smrg * XIAllDevices 2186747b715Smrg */ 21935c4bbdfSmrg bits = (unsigned char *) &mask[1]; 22035c4bbdfSmrg mask->mask_len = (nmasks + 3) / 4; 2216747b715Smrg memset(bits, 0, mask->mask_len * 4); 2226747b715Smrg SetBit(bits, XI_HierarchyChanged); 2236747b715Smrg mask->deviceid = XIAllDevices; 2246747b715Smrg request_XISelectEvent(req, Success); 22535c4bbdfSmrg for (j = 1; j < devices.num_devices; j++) { 2266747b715Smrg mask->deviceid = j; 2276747b715Smrg request_XISelectEvent(req, BadValue); 2286747b715Smrg } 2296747b715Smrg 2306747b715Smrg /* Test 6: 2316747b715Smrg * All bits set minus hierarchy changed bit -> Success 2326747b715Smrg */ 23335c4bbdfSmrg bits = (unsigned char *) &mask[1]; 23435c4bbdfSmrg mask->mask_len = (nmasks + 3) / 4; 2356747b715Smrg memset(bits, 0, mask->mask_len * 4); 2369ace9065Smrg for (j = 0; j <= XI2LASTEVENT; j++) 23735c4bbdfSmrg _set_bit(bits, j); 23835c4bbdfSmrg _clear_bit(bits, XI_HierarchyChanged); 23935c4bbdfSmrg for (j = 1; j < 6; j++) { 2406747b715Smrg mask->deviceid = j; 2416747b715Smrg request_XISelectEvent(req, Success); 2426747b715Smrg } 2436747b715Smrg 24435c4bbdfSmrg mask = 24535c4bbdfSmrg (xXIEventMask *) ((char *) mask + sizeof(xXIEventMask) + 24635c4bbdfSmrg mask->mask_len * 4); 2476747b715Smrg } 2486747b715Smrg} 2496747b715Smrg 25035c4bbdfSmrgstatic void 25135c4bbdfSmrgtest_XISelectEvents(void) 2526747b715Smrg{ 2536747b715Smrg int i; 2546747b715Smrg xXIEventMask *mask; 2556747b715Smrg xXISelectEventsReq *req; 25635c4bbdfSmrg 25735c4bbdfSmrg req = (xXISelectEventsReq *) data; 2586747b715Smrg 2596747b715Smrg request_init(req, XISelectEvents); 2606747b715Smrg 26135c4bbdfSmrg printf("Testing for BadValue on zero-length masks\n"); 2626747b715Smrg /* zero masks are BadValue, regardless of the window */ 2636747b715Smrg req->num_masks = 0; 2646747b715Smrg 2656747b715Smrg req->win = None; 2666747b715Smrg request_XISelectEvent(req, BadValue); 2676747b715Smrg 2686747b715Smrg req->win = ROOT_WINDOW_ID; 2696747b715Smrg request_XISelectEvent(req, BadValue); 2706747b715Smrg 2716747b715Smrg req->win = CLIENT_WINDOW_ID; 2726747b715Smrg request_XISelectEvent(req, BadValue); 2736747b715Smrg 27435c4bbdfSmrg printf("Testing for BadWindow.\n"); 2756747b715Smrg /* None window is BadWindow, regardless of the masks. 2766747b715Smrg * We don't actually need to set the masks here, BadWindow must occur 2776747b715Smrg * before checking the masks. 2786747b715Smrg */ 2796747b715Smrg req->win = None; 2806747b715Smrg req->num_masks = 1; 2816747b715Smrg request_XISelectEvent(req, BadWindow); 2826747b715Smrg 2836747b715Smrg req->num_masks = 2; 2846747b715Smrg request_XISelectEvent(req, BadWindow); 2856747b715Smrg 2866747b715Smrg req->num_masks = 0xFF; 2876747b715Smrg request_XISelectEvent(req, BadWindow); 2886747b715Smrg 2896747b715Smrg /* request size is 3, so 0xFFFC is the highest num_mask that doesn't 2906747b715Smrg * overflow req->length */ 2916747b715Smrg req->num_masks = 0xFFFC; 2926747b715Smrg request_XISelectEvent(req, BadWindow); 2936747b715Smrg 29435c4bbdfSmrg printf("Triggering num_masks/length overflow\n"); 2956747b715Smrg req->win = ROOT_WINDOW_ID; 2966747b715Smrg /* Integer overflow - req->length can't hold that much */ 2976747b715Smrg req->num_masks = 0xFFFF; 2986747b715Smrg request_XISelectEvent(req, BadLength); 2996747b715Smrg 3006747b715Smrg req->win = ROOT_WINDOW_ID; 3016747b715Smrg req->num_masks = 1; 3026747b715Smrg 30335c4bbdfSmrg printf("Triggering bogus mask length error\n"); 30435c4bbdfSmrg mask = (xXIEventMask *) &req[1]; 3056747b715Smrg mask->deviceid = 0; 3066747b715Smrg mask->mask_len = 0xFFFF; 3076747b715Smrg request_XISelectEvent(req, BadLength); 3086747b715Smrg 3096747b715Smrg /* testing various device ids */ 31035c4bbdfSmrg printf("Testing existing device ids.\n"); 31135c4bbdfSmrg for (i = 0; i < 6; i++) { 31235c4bbdfSmrg mask = (xXIEventMask *) &req[1]; 3136747b715Smrg mask->deviceid = i; 3146747b715Smrg mask->mask_len = 1; 3156747b715Smrg req->win = ROOT_WINDOW_ID; 3166747b715Smrg req->num_masks = 1; 3176747b715Smrg request_XISelectEvent(req, Success); 3186747b715Smrg } 3196747b715Smrg 32035c4bbdfSmrg printf("Testing non-existing device ids.\n"); 32135c4bbdfSmrg for (i = 6; i <= 0xFFFF; i++) { 3226747b715Smrg req->win = ROOT_WINDOW_ID; 3236747b715Smrg req->num_masks = 1; 32435c4bbdfSmrg mask = (xXIEventMask *) &req[1]; 3256747b715Smrg mask->deviceid = i; 3266747b715Smrg mask->mask_len = 1; 3276747b715Smrg request_XISelectEvent(req, BadDevice); 3286747b715Smrg } 3296747b715Smrg 3306747b715Smrg request_XISelectEvents_masks(req); 3316747b715Smrg} 3326747b715Smrg 33335c4bbdfSmrgint 3341b5d61b8Smrgprotocol_xiselectevents_test(void) 3356747b715Smrg{ 3366747b715Smrg init_simple(); 3376747b715Smrg 33835c4bbdfSmrg test_XISelectEvents(); 3396747b715Smrg 34035c4bbdfSmrg return 0; 3416747b715Smrg} 342