• Uli Schlachter's avatar
    Fix handling of error connections · ae88512d
    Uli Schlachter authored
    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's avatarUli Schlachter <psychon@znc.in>
    ae88512d