XDrawString issues with long strings

Matthieu Herrb matthieu at herrb.eu
Mon Feb 23 00:09:38 PST 2015


The program below demonstrates an issue with XDrawString. It's not very
clear to me how it should behave if the string that is passed is too
long (the man page does not specify it explicitely) but currently
there are odd things happending.

With an argument of 270000 it will trigger an assertion in xcb_io.c:

[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has
not been called
[xcb] Aborting, sorry about that.
assertion "!xcb_xlib_threads_sequence_lost" failed: file
"/usr/xenocara/lib/libX11/src/xcb_io.c", line 274, function
Abort (core dumped)

With other large values it will trigger a BadLength X Error, but i)
it's not documented that this error can be thrown, ii) from reading
the code I think it's somehow by magic, it's not an intended

With Datalength values greater than 262144, the req->length computation in
Xlib/src/Text.c will overflow, since it's a 16bit value...

#include <X11/Xlib.h>
#include <X11/Xutil.h>

#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

initWindow(Display *display, int xSize, int ySize, GC *gc)
	Window w;
	u_long attributeMask;
	XSetWindowAttributes attribute;
	XGCValues gc_val;
	int screen = DefaultScreen(display);

	attribute.background_pixel = WhitePixel(display, screen);
	attribute.border_pixel = WhitePixel(display, screen);
	attribute.bit_gravity = NorthWestGravity;
	attribute.event_mask = KeyPressMask| ExposureMask;
	attributeMask = CWBorderPixel | CWBackPixel
	    | CWEventMask | CWBitGravity;

	w = XCreateWindow(display, RootWindow(display, screen),
	    0, 0, xSize, ySize, 0, DefaultDepth(display, screen), InputOutput,
	    XDefaultVisual(display, screen), attributeMask, &attribute);

	gc_val.foreground = BlackPixel(display, screen);
	gc_val.background = WhitePixel(display, screen);
	*gc = XCreateGC (display, w, GCForeground|GCBackground, &gc_val);

	/* map the image window */
	XMapWindow(display, w);

eventLoop(Display *display, Window window, GC gc, char *string, size_t n)
	XEvent event;
	int i;
	char c;

	while (1) {
		XNextEvent(display, &event);
		switch(event.type) {
		case KeyPress:
			i = XLookupString(&event.xkey, &c, 1, NULL, NULL);
			if ((i == 1) && ((c == 'q') || (c == 'Q')
				|| (c == '\03'))) {
		case Expose:
			XDrawString(display, window, gc, 5, 50,
			   string, n);

main(int argc, char *argv[])
	Display *d;
	Window w;
	GC gc;
	size_t n;
	char *string;

	if (argc == 2)
		n = atoi(argv[1]);
		n = 10;
	printf("testing for %ld\n", n);
	if ((string = malloc(n)) == NULL)
		err(2, "can't malloc string");
	memset(string, 'A', n - 1);
	string[n-1] = '\0';

	if ((d = XOpenDisplay(NULL)) == NULL)
		errx(2, "Can't open display");
	w = initWindow(d, 1000, 100, &gc);
	eventLoop(d, w, gc, string, n - 1);
	return 0;

Matthieu Herrb

More information about the xorg-devel mailing list