Possible cause for Debian Bug#406559: Xlib converts 32 bit data to 64 bit

I've received the following proposed patch and explanation for one of
the long standing 64 bit issues. Please, if you have been affected by
these bugs, test it. I have no 64 bit systems to try it on.

I uploaded the patch to the wiki, too.

For reference, the debian bugs that this patch might solve are:

#406559: Evolution alarm pop-up breaks sawfish
#403100: Infinite loop after middle-clicking root window

----- Forwarded message from Thadeu Lima de Souza Cascardo <cascardo minaslivre org> -----

Subject: Bug#406559: Xlib converts 32 bit data to 64 bit
From: Thadeu Lima de Souza Cascardo <cascardo minaslivre org>
Date: Tue, 1 Jan 2008 10:11:13 -0200
To: 403100 bugs debian org, 406559 bugs debian org
Envelope-to: rodrigo nul-unu com
Delivery-date: Tue, 01 Jan 2008 06:14:27 -0600
Reply-To: Thadeu Lima de Souza Cascardo <cascardo minaslivre org>,
	406559 bugs debian org
X-Debian-PR-Message: report 406559
X-Debian-PR-Package: sawfish
X-Debian-PR-Keywords: help
X-Debian-PR-Source: sawfish
Organization: Minas Livre
X-Spam_bar: --


I've spent last day investigating this bug. The problem lies whithin
Xlib and the integer format in librep, but the short-term solution goes
in sawfish. I would like to reopen this bug as soon as it is closed and
reassing it to Xlib.

I will describe what I could find out about this bug and attach a patch
that you should test. I also think #403100 and #406559 are the same
bug, but I will wait for a confirmation before merging them.

In fact, I have done my tests based on the experience of #403100,
opening fbpanel, but have watched the same error as in #406559, the bad
argument for make-vector.

The error is triggered when sawfish receives a _NET_WM_DESKTOP from the
client with 0xFFFFFFFF as a parameter, which EWMH describes as sticking
the window for every desktop/workspace. The rep/lisp code is the

         (when (windowp w)
           (let ((desktop (aref data 0)))
             (if (eql desktop #xffffffff)
                 ;; making window sticky
                 (make-window-sticky/workspace w)
               ;; changing the desktop
               (make-window-unsticky/workspace w)
               (send-window-to-workspace-from-first w desktop nil)))))

This means the window will be made stick to all workspaces if the
parameter is 0xFFFFFFFF and will be made unstick and sent to the
desktop-nth workspace.

In 64 bits, this number turns to be 0xFFFFFFFFFFFFFFFF, i.e., a 64-bit
-1. In amd64, adding this 8 more digits solves the problem. We could do
an or for both values as a solution. Using -1 as a solution does not
solve it, since sawfish creates this rep number as unsigned and librep
turns these into BigInt, since it uses 2 bits in the number
representation for distinguishing between types.

So, when calling the client-message-hook from C code, sawfish creates
the vector and the numbers for the parameters. X protocol has 3 formats
for these messages: 20 8-bit parameters, 10 16-bit parameters or 5
32-bit parameters. _NET_WM_DESKTOP has format 32. Xlib, however, uses
long as the type of the 32-bit parameters. And it tries to be smart
when sending this data to the user, converting it from 32 bit unsigned
to the native long format of the host. So, a 32-bit 1's is converted to
64-bit 1's.

So, what is my fix? Well, before creating the numbers for rep from the
64-bit data Xlib gives us, I convert them back to unsigned 32-bit,
using uint32_t type. So, we get 0xFFFFFFFF back. This is also a more
generic fix, since any other messages, not only _NET_WM_DESKTOP, will
be fixed.

As a bonus, I attach my XCB code that will trigger the problem. Please,
try it and the fix in 32-bit too, so we can be sure there will be no

Thadeu Cascardo.

--- sawfish-1.3.1.old/src/events.c	2008-01-01 01:46:12.000000000 -0200
+++ sawfish-1.3.1/src/events.c	2008-01-01 01:45:22.000000000 -0200
@@ -21,6 +21,7 @@
 #include "sawmill.h"
 #include <limits.h>
+#include <stdint.h>
 #include <string.h>
 #include <time.h>
 #include <X11/extensions/shape.h>
@@ -641,7 +642,10 @@
     case 32:
 	data = Fmake_vector (rep_MAKE_INT(5), Qnil);
 	for (i = 0; i < 5; i++)
-	    rep_VECTI(data,i) = rep_make_long_uint (ev->xclient.data.l[i]);
+	{
+	    unsigned long l = (uint32_t) ev->xclient.data.l[i];
+	    rep_VECTI(data,i) = rep_make_long_uint (l);
+	}

#include <xcb/xcb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

X_GetAtom (xcb_connection_t *conn, char *name, size_t name_len)
  xcb_atom_t atom;
  xcb_intern_atom_cookie_t cookie;
  xcb_intern_atom_reply_t *reply;
  cookie = xcb_intern_atom (conn, 0, name_len, name);
  reply = xcb_intern_atom_reply (conn, cookie, NULL);
  if (reply)
      atom = reply->atom;
      free (reply);
      return atom;
  return -1;

main (int argc, char **argv)
  xcb_connection_t *conn;
  xcb_screen_iterator_t iter;
  xcb_client_message_event_t event;
  xcb_void_cookie_t cookie;
  xcb_generic_error_t *error;
  xcb_window_t root;
  xcb_window_t window;
  conn = xcb_connect (NULL, NULL);
  iter = xcb_setup_roots_iterator (xcb_get_setup (conn));
  root = iter.data->root;
  window = xcb_generate_id (conn);
  fprintf (stdout, "Root window has ID %x\n", root);
  fprintf (stdout, "New window has ID %x\n", window);
  cookie = xcb_create_window_checked (conn, 0, window, root, 0, 0,
                                      128, 128, XCB_COPY_FROM_PARENT,
                                      XCB_COPY_FROM_PARENT, 0, NULL);
  error = xcb_request_check (conn, cookie);
  if (error != NULL)
      xcb_request_error_t *rerror = (xcb_request_error_t *) error;
      fprintf (stderr, "Could not create window: ");
      fprintf (stderr, "Response is %d and error code is %d\n",
                        error->response_type, error->error_code);
      fprintf (stderr, "Bad value is %x\n", rerror->bad_value);
      free (error);
  cookie = xcb_map_window_checked (conn, window);
  error = xcb_request_check (conn, cookie);
  if (error != NULL)
      xcb_request_error_t *rerror = (xcb_request_error_t *) error;
      fprintf (stderr, "Could not map window: ");
      fprintf (stderr, "Response is %d and error code is %d\n",
                        error->response_type, error->error_code);
      fprintf (stderr, "Bad value is %x\n", rerror->bad_value);
      free (error);
  event.response_type = XCB_CLIENT_MESSAGE;
  event.format = 32;
  event.sequence = 0xCAFE;
  event.window = window;
  event.type = X_GetAtom (conn, "_NET_WM_DESKTOP",
                          sizeof ("_NET_WM_DESKTOP"));
  event.type = 241;
  memset (event.data.data8, 0, 20);
  event.data.data32[0] = -1;
  event.data.data32[1] = -1;
  cookie = xcb_send_event_checked (conn, 0, root,
                                   XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
                                   (char *) &event);
  error = xcb_request_check (conn, cookie);
  if (error != NULL)
      fprintf (stderr, "Could not send client message: ");
      fprintf (stderr, "Response is %d and error code is %d\n",
                        error->response_type, error->error_code);
      free (error);
  while (1);
  xcb_disconnect (conn);
  return 0;

----- End forwarded message -----

Attachment: signature.asc
Description: Digital signature

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]