XDrawString issues with long strings

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


Hi,

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
"poll_for_event"
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
behaviour.

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>

Window
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);

	return(w);
}
int
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'))) {
				XCloseDisplay(display);
				exit(0);
			}
			break;
		case Expose:
			XDrawString(display, window, gc, 5, 50,
			   string, n);
			break;
		}
	}
}


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

	if (argc == 2)
		n = atoi(argv[1]);
	else
		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