/* gcc -Wall -Wextra -O0 -g -o gdk-pixbuf-2.0-bigendian-crash gdk-pixbuf-2.0-bigendian-crash.c $(pkg-config --libs --cflags gdk-pixbuf-xlib-2.0 x11)
 *
 * Connect to big endian X server:
 * DISPLAY=:1 gdb --args ./gdk-pixbuf-2.0-bigendian-crash
 *
 * When connecting from a big endian machine, the resulting GDK pixbuf
 * will be opaque white in the left 1/4 of the image, and will contain
 * random data in the remaining area. This is because rgb888amsb() will
 * have only written 25% as much data as the target pixbuf can hold (in
 * the #ifndef LITTLE path).
 *
 * When connecting from a little endian machine, glibc will probably
 * crash with an invalid pointer passed in one of the calls to free()
 * at the end of gdk_pixbuf_xlib_get_from_drawable(). This is because
 * rgb888amsb() will have written 400% as much data as the target
 * pixbuf can hold (in the #ifdef LITTLE path).
 *
 * The problem is the function rgb888amsb(), which was never finished.q
 */

#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
#include <X11/Xlib.h>


int main()
{
	Display *display = XOpenDisplay(NULL);
	int screen_num = DefaultScreen(display);
	Window root_win = RootWindow(display, screen_num);


	gdk_pixbuf_xlib_init(display, screen_num);


	int width = 123;
	int height = 123;

	/* This, and the reference to the new pixbuf as part of the
	 * call to gdk_pixbuf_xlib_get_from_drawable(), helps in
	 * triggering glibc's sanity check failure in free().
	 *
	 * I've tested this on openSUSE Leap 42.1.
	 */
	GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
						TRUE,
						8,
						width,
						height);

        (void) gdk_pixbuf_xlib_get_from_drawable(pixbuf,
						root_win,
						xlib_rgb_get_cmap(),
						xlib_rgb_get_visual(),
						0, 0,
						0, 0,
						width,
						height);

	return(0);
}
