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