[Xcb] [PATCH util-keysymy] Fix handling of error connections

Uli Schlachter psychon at znc.in
Sat Feb 22 08:25:33 PST 2014


On 16.11.2013 12:33, Uli Schlachter wrote:
> When an xcb_connection_t goes into an error state, all operations on it will
> fail. This means that after a call to xcb_key_symbols_get_reply(), syms->u.reply
> would still be a NULL pointer and that xcb_get_setup() returns a NULL pointer.
> 
> The only way for xcb_get_setup() to return NULL is for an error connection, but
> xcb_get_keyboard_mapping_reply() could also fail for other reasons. So to fix
> this, all functions need to check for error connections and if syms->u.reply is
> not NULL.
> 
> This was tested with the following C code:
> 
>   #include <xcb_keysyms.h>
>   #include <stdio.h>
>   #include <stdlib.h>
> 
>   int main()
>   {
>   	xcb_connection_t *c = xcb_connect(NULL, NULL);
>   	xcb_key_symbols_t *syms = xcb_key_symbols_alloc(c);
>   	/* The above sent a GetKeyboardMapping request. Let's now break the
>   	 * connection so that it cannot get the reply.
>   	 */
>   	uint32_t max = xcb_get_maximum_request_length(c);
>   	xcb_screen_t *s = xcb_setup_roots_iterator(xcb_get_setup(c)).data;
>   	size_t len = (max << 2) * 2;
>   	void *p = malloc(len);
> 
>   	printf("Sending request of length %d*2=%d\n",
>   			xcb_get_maximum_request_length(c), len);
>   	xcb_change_property(c, XCB_PROP_MODE_REPLACE, s->root,
>   			XCB_ATOM_STRING, XCB_ATOM_STRING, 8, len, p);
>   	free(p);
> 
>   	if (!xcb_connection_has_error(c))
>   		puts("Connection did not break :(");
> 
>   	/* Crash? */
>   	free(xcb_key_symbols_get_keycode(syms, 0xff14));
> 
>   	return 0;
>   }
> 
> Reference: https://awesome.naquadah.org/bugs/index.php?do=details&task_id=1195
> Signed-off-by: Uli Schlachter <psychon at znc.in>

Merged.

> ---
>  keysyms/keysyms.c | 14 ++++++++++----
>  1 file changed, 10 insertions(+), 4 deletions(-)
> 
> diff --git a/keysyms/keysyms.c b/keysyms/keysyms.c
> index daa863f..419c58b 100644
> --- a/keysyms/keysyms.c
> +++ b/keysyms/keysyms.c
> @@ -77,7 +77,7 @@ xcb_key_symbols_alloc (xcb_connection_t *c)
>    xcb_keycode_t     min_keycode;
>    xcb_keycode_t     max_keycode;
> 
> -  if (!c)
> +  if (!c || xcb_connection_has_error(c))
>      return NULL;
> 
>    syms = malloc (sizeof (xcb_key_symbols_t));
> @@ -198,10 +198,13 @@ xcb_keysym_t xcb_key_symbols_get_keysym (xcb_key_symbols_t
> *syms,
>    xcb_keycode_t max_keycode;
>    int        per;
> 
> -  if (!syms)
> +  if (!syms || xcb_connection_has_error(syms->c))
>      return keysym_null;
> 
>    xcb_key_symbols_get_reply (syms, NULL);
> +
> +  if (!syms->u.reply)
> +    return keysym_null;
> 
>    keysyms = xcb_get_keyboard_mapping_keysyms (syms->u.reply);
>    min_keycode = xcb_get_setup (syms->c)->min_keycode;
> @@ -245,12 +248,15 @@ xcb_key_symbols_get_keycode(xcb_key_symbols_t *syms,
>    int j, nresult = 0;
>    xcb_keycode_t i, min, max, *result = NULL, *result_np = NULL;
> 
> -  if(syms)
> +  if(syms && !xcb_connection_has_error(syms->c))
>    {
>        xcb_key_symbols_get_reply (syms, NULL);
>        min = xcb_get_setup(syms->c)->min_keycode;
>        max = xcb_get_setup(syms->c)->max_keycode;
> 
> +      if (!syms->u.reply)
> +        return NULL;
> +
>        for(i = min; i && i <= max; i++)
>            for(j = 0; j < syms->u.reply->keysyms_per_keycode; j++)
>            {
> @@ -298,7 +304,7 @@ int
>  xcb_refresh_keyboard_mapping (xcb_key_symbols_t         *syms,
>  			   xcb_mapping_notify_event_t *event)
>  {
> -  if (event->request == XCB_MAPPING_KEYBOARD && syms) {
> +  if (event->request == XCB_MAPPING_KEYBOARD && syms &&
> !xcb_connection_has_error(syms->c)) {
>      if (syms->tag == TAG_VALUE) {
>        xcb_keycode_t     min_keycode;
>        xcb_keycode_t     max_keycode;
> 


-- 
<alanc> I think someone had a Xprint version of glxgears at one point,
    but benchmarking how many GL pages you can print per second
    was deemed too silly to merge


More information about the Xcb mailing list