protocol-xiselectevents.c revision 6747b715
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"
566747b715Smrg#include "extinit.h" /* for XInputExtensionInit */
576747b715Smrg#include "scrnintstr.h"
586747b715Smrg#include "xiselectev.h"
596747b715Smrg
606747b715Smrg#include "protocol-common.h"
616747b715Smrg#include <glib.h>
626747b715Smrg
636747b715Smrgstatic unsigned char *data[4096 * 20]; /* the request data buffer */
646747b715Smrg
656747b715Smrgint __wrap_XISetEventMask(DeviceIntPtr dev, WindowPtr win, int len, unsigned char* mask)
666747b715Smrg{
676747b715Smrg    return Success;
686747b715Smrg}
696747b715Smrg
706747b715Smrg/* dixLookupWindow requires a lot of setup not necessary for this test.
716747b715Smrg * Simple wrapper that returns either one of the fake root window or the
726747b715Smrg * fake client window. If the requested ID is neither of those wanted,
736747b715Smrg * return whatever the real dixLookupWindow does.
746747b715Smrg */
756747b715Smrgint __wrap_dixLookupWindow(WindowPtr *win, XID id, ClientPtr client, Mask access)
766747b715Smrg{
776747b715Smrg    if (id == root.drawable.id)
786747b715Smrg    {
796747b715Smrg        *win = &root;
806747b715Smrg        return Success;
816747b715Smrg    } else if (id == window.drawable.id)
826747b715Smrg    {
836747b715Smrg        *win = &window;
846747b715Smrg        return Success;
856747b715Smrg    }
866747b715Smrg
876747b715Smrg    return __real_dixLookupWindow(win, id, client, access);
886747b715Smrg}
896747b715Smrg
906747b715Smrg
916747b715Smrgstatic void request_XISelectEvent(xXISelectEventsReq *req, int error)
926747b715Smrg{
936747b715Smrg    char n;
946747b715Smrg    int i;
956747b715Smrg    int rc;
966747b715Smrg    ClientRec client;
976747b715Smrg    xXIEventMask *mask, *next;
986747b715Smrg
996747b715Smrg    req->length = (sz_xXISelectEventsReq/4);
1006747b715Smrg    mask = (xXIEventMask*)&req[1];
1016747b715Smrg    for (i = 0; i < req->num_masks; i++)
1026747b715Smrg    {
1036747b715Smrg        req->length += sizeof(xXIEventMask)/4 + mask->mask_len;
1046747b715Smrg        mask = (xXIEventMask*)((char*)&mask[1] + mask->mask_len * 4);
1056747b715Smrg    }
1066747b715Smrg
1076747b715Smrg    client = init_client(req->length, req);
1086747b715Smrg
1096747b715Smrg    rc = ProcXISelectEvents(&client);
1106747b715Smrg    g_assert(rc == error);
1116747b715Smrg
1126747b715Smrg    client.swapped = TRUE;
1136747b715Smrg
1146747b715Smrg    mask = (xXIEventMask*)&req[1];
1156747b715Smrg    for (i = 0; i < req->num_masks; i++)
1166747b715Smrg    {
1176747b715Smrg        next = (xXIEventMask*)((char*)&mask[1] + mask->mask_len * 4);
1186747b715Smrg        swaps(&mask->deviceid, n);
1196747b715Smrg        swaps(&mask->mask_len, n);
1206747b715Smrg        mask = next;
1216747b715Smrg    }
1226747b715Smrg
1236747b715Smrg    swapl(&req->win, n);
1246747b715Smrg    swaps(&req->length, n);
1256747b715Smrg    swaps(&req->num_masks, n);
1266747b715Smrg    rc = SProcXISelectEvents(&client);
1276747b715Smrg    g_assert(rc == error);
1286747b715Smrg}
1296747b715Smrg
1306747b715Smrgstatic void request_XISelectEvents_masks(xXISelectEventsReq *req)
1316747b715Smrg{
1326747b715Smrg    int i, j;
1336747b715Smrg    xXIEventMask *mask;
1346747b715Smrg    int nmasks = (XI_LASTEVENT + 7)/8;
1356747b715Smrg    unsigned char *bits;
1366747b715Smrg
1376747b715Smrg    mask = (xXIEventMask*)&req[1];
1386747b715Smrg    req->win = ROOT_WINDOW_ID;
1396747b715Smrg
1406747b715Smrg    /* if a clients submits more than 100 masks, consider it insane and untested */
1416747b715Smrg    for (i = 1; i <= 1000; i++)
1426747b715Smrg    {
1436747b715Smrg        req->num_masks = i;
1446747b715Smrg        mask->deviceid = XIAllDevices;
1456747b715Smrg
1466747b715Smrg        /* Test 0:
1476747b715Smrg         * mask_len is 0 -> Success
1486747b715Smrg         */
1496747b715Smrg        mask->mask_len = 0;
1506747b715Smrg        request_XISelectEvent(req, Success);
1516747b715Smrg
1526747b715Smrg        /* Test 1:
1536747b715Smrg         * mask may be larger than needed for XI_LASTEVENT.
1546747b715Smrg         * Test setting each valid mask bit, while leaving unneeded bits 0.
1556747b715Smrg         * -> Success
1566747b715Smrg         */
1576747b715Smrg        bits = (unsigned char*)&mask[1];
1586747b715Smrg        mask->mask_len = (nmasks + 3)/4 * 10;
1596747b715Smrg        memset(bits, 0, mask->mask_len * 4);
1606747b715Smrg        for (j = 0; j <= XI_LASTEVENT; j++)
1616747b715Smrg        {
1626747b715Smrg            SetBit(bits, j);
1636747b715Smrg            request_XISelectEvent(req, Success);
1646747b715Smrg            ClearBit(bits, j);
1656747b715Smrg        }
1666747b715Smrg
1676747b715Smrg        /* Test 2:
1686747b715Smrg         * mask may be larger than needed for XI_LASTEVENT.
1696747b715Smrg         * Test setting all valid mask bits, while leaving unneeded bits 0.
1706747b715Smrg         * -> Success
1716747b715Smrg         */
1726747b715Smrg        bits = (unsigned char*)&mask[1];
1736747b715Smrg        mask->mask_len = (nmasks + 3)/4 * 10;
1746747b715Smrg        memset(bits, 0, mask->mask_len * 4);
1756747b715Smrg
1766747b715Smrg        for (j = 0; j <= XI_LASTEVENT; j++)
1776747b715Smrg        {
1786747b715Smrg            SetBit(bits, j);
1796747b715Smrg            request_XISelectEvent(req, Success);
1806747b715Smrg        }
1816747b715Smrg
1826747b715Smrg        /* Test 3:
1836747b715Smrg         * mask is larger than needed for XI_LASTEVENT. If any unneeded bit
1846747b715Smrg         * is set -> BadValue
1856747b715Smrg         */
1866747b715Smrg        bits = (unsigned char*)&mask[1];
1876747b715Smrg        mask->mask_len = (nmasks + 3)/4 * 10;
1886747b715Smrg        memset(bits, 0, mask->mask_len * 4);
1896747b715Smrg
1906747b715Smrg        for (j = XI_LASTEVENT + 1; j < mask->mask_len * 4; j++)
1916747b715Smrg        {
1926747b715Smrg            SetBit(bits, j);
1936747b715Smrg            request_XISelectEvent(req, BadValue);
1946747b715Smrg            ClearBit(bits, j);
1956747b715Smrg        }
1966747b715Smrg
1976747b715Smrg        /* Test 4:
1986747b715Smrg         * Mask len is a sensible length, only valid bits are set -> Success
1996747b715Smrg         */
2006747b715Smrg        bits = (unsigned char*)&mask[1];
2016747b715Smrg        mask->mask_len = (nmasks + 3)/4;
2026747b715Smrg        memset(bits, 0, mask->mask_len * 4);
2036747b715Smrg        for (j = 0; j <= XI_LASTEVENT; j++)
2046747b715Smrg        {
2056747b715Smrg            SetBit(bits, j);
2066747b715Smrg            request_XISelectEvent(req, Success);
2076747b715Smrg        }
2086747b715Smrg
2096747b715Smrg        /* Test 5:
2106747b715Smrg         * HierarchyChanged bit is BadValue for devices other than
2116747b715Smrg         * XIAllDevices
2126747b715Smrg         */
2136747b715Smrg        bits = (unsigned char*)&mask[1];
2146747b715Smrg        mask->mask_len = (nmasks + 3)/4;
2156747b715Smrg        memset(bits, 0, mask->mask_len * 4);
2166747b715Smrg        SetBit(bits, XI_HierarchyChanged);
2176747b715Smrg        mask->deviceid = XIAllDevices;
2186747b715Smrg        request_XISelectEvent(req, Success);
2196747b715Smrg        for (j = 1; j < devices.num_devices; j++)
2206747b715Smrg        {
2216747b715Smrg            mask->deviceid = j;
2226747b715Smrg            request_XISelectEvent(req, BadValue);
2236747b715Smrg        }
2246747b715Smrg
2256747b715Smrg        /* Test 6:
2266747b715Smrg         * All bits set minus hierarchy changed bit -> Success
2276747b715Smrg         */
2286747b715Smrg        bits = (unsigned char*)&mask[1];
2296747b715Smrg        mask->mask_len = (nmasks + 3)/4;
2306747b715Smrg        memset(bits, 0, mask->mask_len * 4);
2316747b715Smrg        for (j = 0; j <= XI_LASTEVENT; j++)
2326747b715Smrg            SetBit(bits, j);
2336747b715Smrg        ClearBit(bits, XI_HierarchyChanged);
2346747b715Smrg        for (j = 1; j < 6; j++)
2356747b715Smrg        {
2366747b715Smrg            mask->deviceid = j;
2376747b715Smrg            request_XISelectEvent(req, Success);
2386747b715Smrg        }
2396747b715Smrg
2406747b715Smrg        mask = (xXIEventMask*)((char*)mask + sizeof(xXIEventMask) + mask->mask_len * 4);
2416747b715Smrg    }
2426747b715Smrg}
2436747b715Smrg
2446747b715Smrgstatic void test_XISelectEvents(void)
2456747b715Smrg{
2466747b715Smrg    int i;
2476747b715Smrg    xXIEventMask *mask;
2486747b715Smrg    xXISelectEventsReq *req;
2496747b715Smrg    req = (xXISelectEventsReq*)data;
2506747b715Smrg
2516747b715Smrg    request_init(req, XISelectEvents);
2526747b715Smrg
2536747b715Smrg    g_test_message("Testing for BadValue on zero-length masks");
2546747b715Smrg    /* zero masks are BadValue, regardless of the window */
2556747b715Smrg    req->num_masks = 0;
2566747b715Smrg
2576747b715Smrg    req->win = None;
2586747b715Smrg    request_XISelectEvent(req, BadValue);
2596747b715Smrg
2606747b715Smrg    req->win = ROOT_WINDOW_ID;
2616747b715Smrg    request_XISelectEvent(req, BadValue);
2626747b715Smrg
2636747b715Smrg    req->win = CLIENT_WINDOW_ID;
2646747b715Smrg    request_XISelectEvent(req, BadValue);
2656747b715Smrg
2666747b715Smrg    g_test_message("Testing for BadWindow.");
2676747b715Smrg    /* None window is BadWindow, regardless of the masks.
2686747b715Smrg     * We don't actually need to set the masks here, BadWindow must occur
2696747b715Smrg     * before checking the masks.
2706747b715Smrg     */
2716747b715Smrg    req->win = None;
2726747b715Smrg    req->num_masks = 1;
2736747b715Smrg    request_XISelectEvent(req, BadWindow);
2746747b715Smrg
2756747b715Smrg    req->num_masks = 2;
2766747b715Smrg    request_XISelectEvent(req, BadWindow);
2776747b715Smrg
2786747b715Smrg    req->num_masks = 0xFF;
2796747b715Smrg    request_XISelectEvent(req, BadWindow);
2806747b715Smrg
2816747b715Smrg    /* request size is 3, so 0xFFFC is the highest num_mask that doesn't
2826747b715Smrg     * overflow req->length */
2836747b715Smrg    req->num_masks = 0xFFFC;
2846747b715Smrg    request_XISelectEvent(req, BadWindow);
2856747b715Smrg
2866747b715Smrg    g_test_message("Triggering num_masks/length overflow");
2876747b715Smrg    req->win = ROOT_WINDOW_ID;
2886747b715Smrg    /* Integer overflow - req->length can't hold that much */
2896747b715Smrg    req->num_masks = 0xFFFF;
2906747b715Smrg    request_XISelectEvent(req, BadLength);
2916747b715Smrg
2926747b715Smrg    req->win = ROOT_WINDOW_ID;
2936747b715Smrg    req->num_masks = 1;
2946747b715Smrg
2956747b715Smrg    g_test_message("Triggering bogus mask length error");
2966747b715Smrg    mask = (xXIEventMask*)&req[1];
2976747b715Smrg    mask->deviceid = 0;
2986747b715Smrg    mask->mask_len = 0xFFFF;
2996747b715Smrg    request_XISelectEvent(req, BadLength);
3006747b715Smrg
3016747b715Smrg    /* testing various device ids */
3026747b715Smrg    g_test_message("Testing existing device ids.");
3036747b715Smrg    for (i = 0; i < 6; i++)
3046747b715Smrg    {
3056747b715Smrg        mask = (xXIEventMask*)&req[1];
3066747b715Smrg        mask->deviceid = i;
3076747b715Smrg        mask->mask_len = 1;
3086747b715Smrg        req->win = ROOT_WINDOW_ID;
3096747b715Smrg        req->num_masks = 1;
3106747b715Smrg        request_XISelectEvent(req, Success);
3116747b715Smrg    }
3126747b715Smrg
3136747b715Smrg    g_test_message("Testing non-existing device ids.");
3146747b715Smrg    for (i = 6; i <= 0xFFFF; i++)
3156747b715Smrg    {
3166747b715Smrg        req->win = ROOT_WINDOW_ID;
3176747b715Smrg        req->num_masks = 1;
3186747b715Smrg        mask = (xXIEventMask*)&req[1];
3196747b715Smrg        mask->deviceid = i;
3206747b715Smrg        mask->mask_len = 1;
3216747b715Smrg        request_XISelectEvent(req, BadDevice);
3226747b715Smrg    }
3236747b715Smrg
3246747b715Smrg    request_XISelectEvents_masks(req);
3256747b715Smrg}
3266747b715Smrg
3276747b715Smrgint main(int argc, char** argv)
3286747b715Smrg{
3296747b715Smrg    g_test_init(&argc, &argv,NULL);
3306747b715Smrg    g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
3316747b715Smrg
3326747b715Smrg    init_simple();
3336747b715Smrg
3346747b715Smrg    g_test_add_func("/xi2/protocol/XISelectEvents", test_XISelectEvents);
3356747b715Smrg
3366747b715Smrg    return g_test_run();
3376747b715Smrg}
3386747b715Smrg
339