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
24ed6184dfSmrg/* Test relies on assert() */
25ed6184dfSmrg#undef NDEBUG
26ed6184dfSmrg
276747b715Smrg#ifdef HAVE_DIX_CONFIG_H
286747b715Smrg#include <dix-config.h>
296747b715Smrg#endif
306747b715Smrg
316747b715Smrg/*
326747b715Smrg * Protocol testing for XISelectEvents request.
336747b715Smrg *
346747b715Smrg * Test approach:
356747b715Smrg *
366747b715Smrg * Wrap XISetEventMask to intercept when the server tries to apply the event
376747b715Smrg * mask. Ensure that the mask passed in is equivalent to the one supplied by
386747b715Smrg * the client. Ensure that invalid devices and invalid masks return errors
396747b715Smrg * as appropriate.
406747b715Smrg *
416747b715Smrg * Tests included:
426747b715Smrg * BadValue for num_masks < 0
436747b715Smrg * BadWindow for invalid windows
446747b715Smrg * BadDevice for non-existing devices
456747b715Smrg * BadImplemenation for devices >= 0xFF
466747b715Smrg * BadValue if HierarchyChanged bit is set for devices other than
476747b715Smrg *          XIAllDevices
486747b715Smrg * BadValue for invalid mask bits
496747b715Smrg * Sucecss for excessive mask lengths
506747b715Smrg *
516747b715Smrg */
526747b715Smrg
536747b715Smrg#include <stdint.h>
546747b715Smrg#include <X11/X.h>
556747b715Smrg#include <X11/Xproto.h>
566747b715Smrg#include <X11/extensions/XI2proto.h>
576747b715Smrg#include "inputstr.h"
586747b715Smrg#include "windowstr.h"
5935c4bbdfSmrg#include "extinit.h"            /* for XInputExtensionInit */
606747b715Smrg#include "scrnintstr.h"
6135c4bbdfSmrg#include "exglobals.h"
626747b715Smrg#include "xiselectev.h"
636747b715Smrg
646747b715Smrg#include "protocol-common.h"
656747b715Smrg
6635c4bbdfSmrgstatic unsigned char *data[4096 * 20];  /* the request data buffer */
676747b715Smrg
685a7dfde8Smrgextern ClientRec client_window;
691b5d61b8Smrg
7035c4bbdfSmrgint
711b5d61b8Smrg__real_XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
721b5d61b8Smrg                      int len, unsigned char *mask);
736747b715Smrg
7435c4bbdfSmrgint
751b5d61b8Smrg__wrap_XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
761b5d61b8Smrg                      int len, unsigned char *mask)
776747b715Smrg{
781b5d61b8Smrg    if (!enable_XISetEventMask_wrap)
791b5d61b8Smrg        return __real_XISetEventMask(dev, win, client, len, mask);
806747b715Smrg
811b5d61b8Smrg    return Success;
826747b715Smrg}
836747b715Smrg
8435c4bbdfSmrgstatic void
8535c4bbdfSmrgrequest_XISelectEvent(xXISelectEventsReq * req, int error)
866747b715Smrg{
876747b715Smrg    int i;
886747b715Smrg    int rc;
896747b715Smrg    ClientRec client;
906747b715Smrg    xXIEventMask *mask, *next;
916747b715Smrg
9235c4bbdfSmrg    req->length = (sz_xXISelectEventsReq / 4);
9335c4bbdfSmrg    mask = (xXIEventMask *) &req[1];
9435c4bbdfSmrg    for (i = 0; i < req->num_masks; i++) {
9535c4bbdfSmrg        req->length += sizeof(xXIEventMask) / 4 + mask->mask_len;
9635c4bbdfSmrg        mask = (xXIEventMask *) ((char *) &mask[1] + mask->mask_len * 4);
976747b715Smrg    }
986747b715Smrg
996747b715Smrg    client = init_client(req->length, req);
1006747b715Smrg
1016747b715Smrg    rc = ProcXISelectEvents(&client);
10235c4bbdfSmrg    assert(rc == error);
1036747b715Smrg
1046747b715Smrg    client.swapped = TRUE;
1056747b715Smrg
10635c4bbdfSmrg    mask = (xXIEventMask *) &req[1];
10735c4bbdfSmrg    for (i = 0; i < req->num_masks; i++) {
10835c4bbdfSmrg        next = (xXIEventMask *) ((char *) &mask[1] + mask->mask_len * 4);
10935c4bbdfSmrg        swaps(&mask->deviceid);
11035c4bbdfSmrg        swaps(&mask->mask_len);
1116747b715Smrg        mask = next;
1126747b715Smrg    }
1136747b715Smrg
11435c4bbdfSmrg    swapl(&req->win);
11535c4bbdfSmrg    swaps(&req->length);
11635c4bbdfSmrg    swaps(&req->num_masks);
1176747b715Smrg    rc = SProcXISelectEvents(&client);
11835c4bbdfSmrg    assert(rc == error);
11935c4bbdfSmrg}
12035c4bbdfSmrg
12135c4bbdfSmrgstatic void
12235c4bbdfSmrg_set_bit(unsigned char *bits, int bit)
12335c4bbdfSmrg{
12435c4bbdfSmrg    SetBit(bits, bit);
12535c4bbdfSmrg    if (bit >= XI_TouchBegin && bit <= XI_TouchOwnership) {
12635c4bbdfSmrg        SetBit(bits, XI_TouchBegin);
12735c4bbdfSmrg        SetBit(bits, XI_TouchUpdate);
12835c4bbdfSmrg        SetBit(bits, XI_TouchEnd);
12935c4bbdfSmrg    }
130ed6184dfSmrg    if (bit >= XI_GesturePinchBegin && bit <= XI_GesturePinchEnd) {
131ed6184dfSmrg        SetBit(bits, XI_GesturePinchBegin);
132ed6184dfSmrg        SetBit(bits, XI_GesturePinchUpdate);
133ed6184dfSmrg        SetBit(bits, XI_GesturePinchEnd);
134ed6184dfSmrg    }
135ed6184dfSmrg    if (bit >= XI_GestureSwipeBegin && bit <= XI_GestureSwipeEnd) {
136ed6184dfSmrg        SetBit(bits, XI_GestureSwipeBegin);
137ed6184dfSmrg        SetBit(bits, XI_GestureSwipeUpdate);
138ed6184dfSmrg        SetBit(bits, XI_GestureSwipeEnd);
139ed6184dfSmrg    }
14035c4bbdfSmrg}
14135c4bbdfSmrg
14235c4bbdfSmrgstatic void
14335c4bbdfSmrg_clear_bit(unsigned char *bits, int bit)
14435c4bbdfSmrg{
14535c4bbdfSmrg    ClearBit(bits, bit);
14635c4bbdfSmrg    if (bit >= XI_TouchBegin && bit <= XI_TouchOwnership) {
14735c4bbdfSmrg        ClearBit(bits, XI_TouchBegin);
14835c4bbdfSmrg        ClearBit(bits, XI_TouchUpdate);
14935c4bbdfSmrg        ClearBit(bits, XI_TouchEnd);
15035c4bbdfSmrg    }
151ed6184dfSmrg    if (bit >= XI_GesturePinchBegin && bit <= XI_GesturePinchEnd) {
152ed6184dfSmrg        ClearBit(bits, XI_GesturePinchBegin);
153ed6184dfSmrg        ClearBit(bits, XI_GesturePinchUpdate);
154ed6184dfSmrg        ClearBit(bits, XI_GesturePinchEnd);
155ed6184dfSmrg    }
156ed6184dfSmrg    if (bit >= XI_GestureSwipeBegin && bit <= XI_GestureSwipeEnd) {
157ed6184dfSmrg        ClearBit(bits, XI_GestureSwipeBegin);
158ed6184dfSmrg        ClearBit(bits, XI_GestureSwipeUpdate);
159ed6184dfSmrg        ClearBit(bits, XI_GestureSwipeEnd);
160ed6184dfSmrg    }
1616747b715Smrg}
1626747b715Smrg
16335c4bbdfSmrgstatic void
16435c4bbdfSmrgrequest_XISelectEvents_masks(xXISelectEventsReq * req)
1656747b715Smrg{
1666747b715Smrg    int i, j;
1676747b715Smrg    xXIEventMask *mask;
168ed6184dfSmrg    int nmasks = XI2MASKSIZE;
1696747b715Smrg    unsigned char *bits;
1706747b715Smrg
17135c4bbdfSmrg    mask = (xXIEventMask *) &req[1];
1726747b715Smrg    req->win = ROOT_WINDOW_ID;
1736747b715Smrg
1746747b715Smrg    /* if a clients submits more than 100 masks, consider it insane and untested */
17535c4bbdfSmrg    for (i = 1; i <= 1000; i++) {
1766747b715Smrg        req->num_masks = i;
1776747b715Smrg        mask->deviceid = XIAllDevices;
1786747b715Smrg
1796747b715Smrg        /* Test 0:
1806747b715Smrg         * mask_len is 0 -> Success
1816747b715Smrg         */
1826747b715Smrg        mask->mask_len = 0;
1836747b715Smrg        request_XISelectEvent(req, Success);
1846747b715Smrg
1856747b715Smrg        /* Test 1:
1869ace9065Smrg         * mask may be larger than needed for XI2LASTEVENT.
1876747b715Smrg         * Test setting each valid mask bit, while leaving unneeded bits 0.
1886747b715Smrg         * -> Success
1896747b715Smrg         */
19035c4bbdfSmrg        bits = (unsigned char *) &mask[1];
19135c4bbdfSmrg        mask->mask_len = (nmasks + 3) / 4 * 10;
1926747b715Smrg        memset(bits, 0, mask->mask_len * 4);
19335c4bbdfSmrg        for (j = 0; j <= XI2LASTEVENT; j++) {
19435c4bbdfSmrg            _set_bit(bits, j);
1956747b715Smrg            request_XISelectEvent(req, Success);
19635c4bbdfSmrg            _clear_bit(bits, j);
1976747b715Smrg        }
1986747b715Smrg
1996747b715Smrg        /* Test 2:
2009ace9065Smrg         * mask may be larger than needed for XI2LASTEVENT.
2016747b715Smrg         * Test setting all valid mask bits, while leaving unneeded bits 0.
2026747b715Smrg         * -> Success
2036747b715Smrg         */
20435c4bbdfSmrg        bits = (unsigned char *) &mask[1];
20535c4bbdfSmrg        mask->mask_len = (nmasks + 3) / 4 * 10;
2066747b715Smrg        memset(bits, 0, mask->mask_len * 4);
2076747b715Smrg
20835c4bbdfSmrg        for (j = 0; j <= XI2LASTEVENT; j++) {
20935c4bbdfSmrg            _set_bit(bits, j);
2106747b715Smrg            request_XISelectEvent(req, Success);
2116747b715Smrg        }
2126747b715Smrg
2136747b715Smrg        /* Test 3:
2149ace9065Smrg         * mask is larger than needed for XI2LASTEVENT. If any unneeded bit
2156747b715Smrg         * is set -> BadValue
2166747b715Smrg         */
21735c4bbdfSmrg        bits = (unsigned char *) &mask[1];
21835c4bbdfSmrg        mask->mask_len = (nmasks + 3) / 4 * 10;
2196747b715Smrg        memset(bits, 0, mask->mask_len * 4);
2206747b715Smrg
22135c4bbdfSmrg        for (j = XI2LASTEVENT + 1; j < mask->mask_len * 4; j++) {
22235c4bbdfSmrg            _set_bit(bits, j);
2236747b715Smrg            request_XISelectEvent(req, BadValue);
22435c4bbdfSmrg            _clear_bit(bits, j);
2256747b715Smrg        }
2266747b715Smrg
2276747b715Smrg        /* Test 4:
2286747b715Smrg         * Mask len is a sensible length, only valid bits are set -> Success
2296747b715Smrg         */
23035c4bbdfSmrg        bits = (unsigned char *) &mask[1];
23135c4bbdfSmrg        mask->mask_len = (nmasks + 3) / 4;
2326747b715Smrg        memset(bits, 0, mask->mask_len * 4);
23335c4bbdfSmrg        for (j = 0; j <= XI2LASTEVENT; j++) {
23435c4bbdfSmrg            _set_bit(bits, j);
2356747b715Smrg            request_XISelectEvent(req, Success);
2366747b715Smrg        }
2376747b715Smrg
2386747b715Smrg        /* Test 5:
239ed6184dfSmrg         * Mask len is 1 and XI_GestureSwipeEnd is set outside the mask.
240ed6184dfSmrg         * That bit should be ignored -> Success
241ed6184dfSmrg         */
242ed6184dfSmrg        bits = (unsigned char *) &mask[1];
243ed6184dfSmrg        mask->mask_len = 1;
244ed6184dfSmrg        memset(bits, 0, 5);
245ed6184dfSmrg        SetBit(bits, XI_ButtonPress); // does not matter which one
246ed6184dfSmrg        SetBit(bits, XI_GestureSwipeEnd);
247ed6184dfSmrg        request_XISelectEvent(req, Success);
248ed6184dfSmrg
249ed6184dfSmrg        /* Test 6:
2506747b715Smrg         * HierarchyChanged bit is BadValue for devices other than
2516747b715Smrg         * XIAllDevices
2526747b715Smrg         */
25335c4bbdfSmrg        bits = (unsigned char *) &mask[1];
25435c4bbdfSmrg        mask->mask_len = (nmasks + 3) / 4;
2556747b715Smrg        memset(bits, 0, mask->mask_len * 4);
2566747b715Smrg        SetBit(bits, XI_HierarchyChanged);
2576747b715Smrg        mask->deviceid = XIAllDevices;
2586747b715Smrg        request_XISelectEvent(req, Success);
25935c4bbdfSmrg        for (j = 1; j < devices.num_devices; j++) {
2606747b715Smrg            mask->deviceid = j;
2616747b715Smrg            request_XISelectEvent(req, BadValue);
2626747b715Smrg        }
2636747b715Smrg
264ed6184dfSmrg        /* Test 7:
2656747b715Smrg         * All bits set minus hierarchy changed bit -> Success
2666747b715Smrg         */
26735c4bbdfSmrg        bits = (unsigned char *) &mask[1];
26835c4bbdfSmrg        mask->mask_len = (nmasks + 3) / 4;
2696747b715Smrg        memset(bits, 0, mask->mask_len * 4);
2709ace9065Smrg        for (j = 0; j <= XI2LASTEVENT; j++)
27135c4bbdfSmrg            _set_bit(bits, j);
27235c4bbdfSmrg        _clear_bit(bits, XI_HierarchyChanged);
27335c4bbdfSmrg        for (j = 1; j < 6; j++) {
2746747b715Smrg            mask->deviceid = j;
2756747b715Smrg            request_XISelectEvent(req, Success);
2766747b715Smrg        }
2776747b715Smrg
27835c4bbdfSmrg        mask =
27935c4bbdfSmrg            (xXIEventMask *) ((char *) mask + sizeof(xXIEventMask) +
28035c4bbdfSmrg                              mask->mask_len * 4);
2816747b715Smrg    }
2826747b715Smrg}
2836747b715Smrg
28435c4bbdfSmrgstatic void
28535c4bbdfSmrgtest_XISelectEvents(void)
2866747b715Smrg{
2876747b715Smrg    int i;
2886747b715Smrg    xXIEventMask *mask;
2896747b715Smrg    xXISelectEventsReq *req;
29035c4bbdfSmrg
29135c4bbdfSmrg    req = (xXISelectEventsReq *) data;
2926747b715Smrg
2936747b715Smrg    request_init(req, XISelectEvents);
2946747b715Smrg
29535c4bbdfSmrg    printf("Testing for BadValue on zero-length masks\n");
2966747b715Smrg    /* zero masks are BadValue, regardless of the window */
2976747b715Smrg    req->num_masks = 0;
2986747b715Smrg
2996747b715Smrg    req->win = None;
3006747b715Smrg    request_XISelectEvent(req, BadValue);
3016747b715Smrg
3026747b715Smrg    req->win = ROOT_WINDOW_ID;
3036747b715Smrg    request_XISelectEvent(req, BadValue);
3046747b715Smrg
3056747b715Smrg    req->win = CLIENT_WINDOW_ID;
3066747b715Smrg    request_XISelectEvent(req, BadValue);
3076747b715Smrg
30835c4bbdfSmrg    printf("Testing for BadWindow.\n");
3096747b715Smrg    /* None window is BadWindow, regardless of the masks.
3106747b715Smrg     * We don't actually need to set the masks here, BadWindow must occur
3116747b715Smrg     * before checking the masks.
3126747b715Smrg     */
3136747b715Smrg    req->win = None;
3146747b715Smrg    req->num_masks = 1;
3156747b715Smrg    request_XISelectEvent(req, BadWindow);
3166747b715Smrg
3176747b715Smrg    req->num_masks = 2;
3186747b715Smrg    request_XISelectEvent(req, BadWindow);
3196747b715Smrg
3206747b715Smrg    req->num_masks = 0xFF;
3216747b715Smrg    request_XISelectEvent(req, BadWindow);
3226747b715Smrg
3236747b715Smrg    /* request size is 3, so 0xFFFC is the highest num_mask that doesn't
3246747b715Smrg     * overflow req->length */
3256747b715Smrg    req->num_masks = 0xFFFC;
3266747b715Smrg    request_XISelectEvent(req, BadWindow);
3276747b715Smrg
32835c4bbdfSmrg    printf("Triggering num_masks/length overflow\n");
3296747b715Smrg    req->win = ROOT_WINDOW_ID;
3306747b715Smrg    /* Integer overflow - req->length can't hold that much */
3316747b715Smrg    req->num_masks = 0xFFFF;
3326747b715Smrg    request_XISelectEvent(req, BadLength);
3336747b715Smrg
3346747b715Smrg    req->win = ROOT_WINDOW_ID;
3356747b715Smrg    req->num_masks = 1;
3366747b715Smrg
33735c4bbdfSmrg    printf("Triggering bogus mask length error\n");
33835c4bbdfSmrg    mask = (xXIEventMask *) &req[1];
3396747b715Smrg    mask->deviceid = 0;
3406747b715Smrg    mask->mask_len = 0xFFFF;
3416747b715Smrg    request_XISelectEvent(req, BadLength);
3426747b715Smrg
3436747b715Smrg    /* testing various device ids */
34435c4bbdfSmrg    printf("Testing existing device ids.\n");
34535c4bbdfSmrg    for (i = 0; i < 6; i++) {
34635c4bbdfSmrg        mask = (xXIEventMask *) &req[1];
3476747b715Smrg        mask->deviceid = i;
3486747b715Smrg        mask->mask_len = 1;
3496747b715Smrg        req->win = ROOT_WINDOW_ID;
3506747b715Smrg        req->num_masks = 1;
3516747b715Smrg        request_XISelectEvent(req, Success);
3526747b715Smrg    }
3536747b715Smrg
35435c4bbdfSmrg    printf("Testing non-existing device ids.\n");
35535c4bbdfSmrg    for (i = 6; i <= 0xFFFF; i++) {
3566747b715Smrg        req->win = ROOT_WINDOW_ID;
3576747b715Smrg        req->num_masks = 1;
35835c4bbdfSmrg        mask = (xXIEventMask *) &req[1];
3596747b715Smrg        mask->deviceid = i;
3606747b715Smrg        mask->mask_len = 1;
3616747b715Smrg        request_XISelectEvent(req, BadDevice);
3626747b715Smrg    }
3636747b715Smrg
3646747b715Smrg    request_XISelectEvents_masks(req);
3656747b715Smrg}
3666747b715Smrg
36735c4bbdfSmrgint
3681b5d61b8Smrgprotocol_xiselectevents_test(void)
3696747b715Smrg{
3706747b715Smrg    init_simple();
3716747b715Smrg
37235c4bbdfSmrg    test_XISelectEvents();
3736747b715Smrg
37435c4bbdfSmrg    return 0;
3756747b715Smrg}
376