xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

protocol-xiselectevents.c (11336B)


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