[PATCH xts] Xlib4: Fix XMapSubwindows test 9

Peter Harris pharris at opentext.com
Mon Apr 29 12:31:42 PDT 2013


XMapSubwindows-9 creates a number of overlapping sibling windows, then
checks that a GetImage of each window is filled after processing all
Expose events.

This is invalid per the spec, as areas of a GetImage that are obscured
by a sibling are undefined. In particular, current servers intentionally
blank any area obscured by a sibling for security reasons.

Change XMapSubwindows to only verify the parts of the GetImage that are
not obscured by a sibling window.

Signed-off-by: Peter Harris <pharris at opentext.com>
---

This change would have been much smaller (and also a bit riskier) if I
had rewritten checkarea to call checkregion. This would also eliminate
the need for a separate dorgnerr function. I could be persuaded to
refactor and resubmit.

 xts5/Xlib4/XMapSubwindows/XMapSubwindows.m |   22 ++++-
 xts5/include/xtlibproto.h                  |    2 +
 xts5/src/lib/checkarea.c                   |  148 ++++++++++++++++++++++++++++
 3 files changed, 171 insertions(+), 1 deletions(-)

diff --git a/xts5/Xlib4/XMapSubwindows/XMapSubwindows.m b/xts5/Xlib4/XMapSubwindows/XMapSubwindows.m
index 7f1e708..6a582ca 100644
--- a/xts5/Xlib4/XMapSubwindows/XMapSubwindows.m
+++ b/xts5/Xlib4/XMapSubwindows/XMapSubwindows.m
@@ -1,4 +1,5 @@
 Copyright (c) 2005 X.Org Foundation L.L.C.
+Copyright (c) Open Text SA and/or Open Text ULC
 
 Permission is hereby granted, free of charge, to any person obtaining a copy of
 this software and associated documentation files (the "Software"), to deal in
@@ -822,7 +823,26 @@ int 	i;
 	for (i = 1; i < NELEM(T1); i++)
 		exposefill(display, bt[i].wid);
 	for (i = 1; i < NELEM(T1); i++) {
-		if (exposecheck(display, bt[i].wid))
+		/* Compute unobscured region */
+		int j;
+		XRectangle rect;
+		Region sub = makeregion();
+		Region rgn = makeregion();
+		rect.x = 0;
+		rect.y = 0;
+		rect.width = bt[i].width;
+		rect.height = bt[i].height;
+		XUnionRectWithRegion(&rect, rgn, rgn);
+		for (j = i+1; j < NELEM(T1); j++) {
+			XSubtractRegion(sub, sub, sub);
+			rect.x = bt[j].x - bt[i].x;
+			rect.y = bt[j].y - bt[i].y;
+			rect.width = bt[j].width;
+			rect.height = bt[j].height;
+			XUnionRectWithRegion(&rect, sub, sub);
+			XSubtractRegion(rgn, sub, rgn);
+		}
+		if (checkregion(display, bt[i].wid, rgn, W_FG, W_FG, CHECK_IN))
 			CHECK;
 		else {
 			report("Neither Expose events or backing store processing");
diff --git a/xts5/include/xtlibproto.h b/xts5/include/xtlibproto.h
index fdfd443..33bd1de 100644
--- a/xts5/include/xtlibproto.h
+++ b/xts5/include/xtlibproto.h
@@ -207,6 +207,7 @@ int nextsupvis(XVisualInfo **vi);
 int nsupvis(void);
 Status checkarea(Display *disp, Drawable d, register struct area *ap, unsigned long  inpix, unsigned long  outpix, int  flags);
 Status checkclear(Display *disp, Drawable d);
+Status checkregion(Display *disp, Drawable d, Region rgn, unsigned long inpix, unsigned long outpix, int flags);
 void getsize(Display *disp, Drawable d, unsigned int  *widthp, unsigned int  *heightp);
 unsigned int getdepth(Display *disp, Drawable d);
 void pattern(Display *disp, Drawable d);
@@ -445,6 +446,7 @@ int nextsupvis();
 int nsupvis();
 Status checkarea();
 Status checkclear();
+Status checkregion();
 void getsize();
 unsigned int getdepth();
 void pattern();
diff --git a/xts5/src/lib/checkarea.c b/xts5/src/lib/checkarea.c
index 88934bc..81bcb34 100644
--- a/xts5/src/lib/checkarea.c
+++ b/xts5/src/lib/checkarea.c
@@ -1,5 +1,6 @@
 /*
 Copyright (c) 2005 X.Org Foundation L.L.C.
+Copyright (c) Open Text SA and/or Open Text ULC
 
 Permission is hereby granted, free of charge, to any person obtaining a copy of
 this software and associated documentation files (the "Software"), to deal in
@@ -122,6 +123,7 @@ purpose.  It is provided "as is" without express or implied warranty.
 #include	"pixval.h"
 
 static	void	doerr();
+static	void	dorgnerr(XImage *im, Region rgn, unsigned long inpix, unsigned long outpix, int flags);
 
 #define	inarea(ap, x, y)	\
 (\
@@ -136,6 +138,7 @@ static	void	doerr();
  * If flags are CHECK_OUT only the outside is checked.
  * flags of 0 or CHECK_ALL check both.
  * If ap is NULL then the whole window is checked.  (See also checkclear)
+ * (See also checkregion)
  */
 Status
 checkarea(disp, d, ap, inpix, outpix, flags)
@@ -241,6 +244,94 @@ Drawable	d;
 }
 
 /*
+ * Same as checkarea, except it takes a 'Region' instead of an 'area'
+ */
+Status
+checkregion(Display *disp, Drawable d, Region rgn,
+            unsigned long inpix, unsigned long outpix, int flags)
+{
+int 	x, y;
+XImage	*im;
+int 	xorig;
+int 	yorig;
+unsigned int 	width;
+unsigned int 	height;
+unsigned long	pix;
+int 	inloopflag = 0;
+
+	if (flags == 0)
+		flags = CHECK_ALL;
+	if ((flags & CHECK_ALL) == 0) {
+		report("assert error in checkregion()");
+		printf("assert error in checkregion()\n");
+		exit(1);
+	}
+
+	getsize(disp, d, &width, &height);
+
+	/*
+	 * If a NULL region has been given then error out
+	 */
+	if (rgn == NULL) {
+		report("assert error in checkregion()");
+		printf("assert error in checkregion()\n");
+		exit(1);
+	}
+
+	im = XGetImage(disp, d, 0, 0, width, height, AllPlanes, ZPixmap);
+	if (im == (XImage*)0) {
+		delete("XGetImage failed");
+		return(False);
+	}
+
+	/*
+	 * If we are only checking inside then only examine that part.
+	 */
+	if ((flags & CHECK_ALL) == CHECK_IN) {
+		XRectangle rect;
+		XClipBox(rgn, &rect);
+		xorig = rect.x;
+		yorig = rect.y;
+		width = rect.width;
+		height = rect.height;
+	} else {
+		xorig = 0;
+		yorig = 0;
+	}
+
+	for (y = yorig; y < yorig+height; y++) {
+		for (x = xorig; x < xorig+width; x++) {
+			inloopflag = 1;
+			pix = XGetPixel(im, x, y);
+			if (XPointInRegion(rgn, x, y)) {
+				if (pix != inpix && (flags & CHECK_IN)) {
+					if (!(flags & CHECK_DIFFER))
+						dorgnerr(im, rgn, inpix, outpix, flags);
+					XDestroyImage(im);
+					return(False);
+				}
+			} else {
+				if (pix != outpix && (flags & CHECK_OUT)) {
+					if (!(flags & CHECK_DIFFER))
+						dorgnerr(im, rgn, inpix, outpix, flags);
+					XDestroyImage(im);
+					return(False);
+				}
+			}
+		}
+	}
+
+	/* This is to catch bugs */
+	if (inloopflag == 0) {
+		delete("No pixels checked in checkregion - internal error");
+		XDestroyImage(im);
+		return(False);
+	}
+	XDestroyImage(im);
+	return(True);
+}
+
+/*
  * Make up an error file by faking a known good image.
  */
 static void
@@ -301,3 +392,60 @@ extern	int 	Errnum;
 	XDestroyImage(good);
 	XDestroyImage(bad);
 }
+
+/*
+ * Make up an error file by faking a known good image.
+ */
+static void
+dorgnerr(XImage *im, Region rgn, unsigned long inpix, unsigned long outpix, int flags)
+{
+XImage	*good;
+XImage	*bad;
+int 	x, y;
+char	name[32];
+extern	int 	Errnum;
+
+	flags &= CHECK_ALL;
+
+	/*
+	 * Make copies of the image, because we are going to scribble into them.
+	 */
+	good = XSubImage(im, 0, 0, im->width, im->height);
+	bad = XSubImage(im, 0, 0, im->width, im->height);
+
+	for (y = 0; y < im->height; y++) {
+		for (x = 0; x < im->width; x++) {
+			/*
+			 * For parts of the image that we are not interested in
+			 * then we set both good and bad to W_BG.
+			 * Otherwise build up a good image.
+			 */
+			if (XPointInRegion(rgn, x, y)) {
+				if (flags & CHECK_IN) {
+					XPutPixel(good, x, y, inpix);
+				} else {
+					XPutPixel(good, x, y, W_BG);
+					XPutPixel(bad, x, y, W_BG);
+				}
+			} else {
+				if (flags & CHECK_OUT) {
+					XPutPixel(good, x, y, outpix);
+				} else {
+					XPutPixel(good, x, y, W_BG);
+					XPutPixel(bad, x, y, W_BG);
+				}
+			}
+		}
+	}
+	report("Pixel mismatch in image");
+
+	/* Making up an error file should be a subroutine.. */
+	sprintf(name, "Err%04d.err", Errnum++);
+	report("See file %s for details", name);
+	unlink(name);
+	dumpimage(bad, name, (struct area *)0);
+	dumpimage(good, name, (struct area *)0);
+
+	XDestroyImage(good);
+	XDestroyImage(bad);
+}
-- 
1.7.2.5



More information about the xorg-devel mailing list