[PATCH] Bug #22804: Reject out of bounds XGetImage requests

Aaron Plattner aplattner at nvidia.com
Fri Jul 17 10:51:45 PDT 2009


The XGetImage man page states:

    If the drawable is a window, the window must be viewable, and it must be the
    case that if there were no inferiors or overlapping windows, the specified
    rectangle of the window would be fully visible on the screen and wholly
    contained within the outside edges of the window, or a BadMatch error
    results.  Note that the borders of the window can be included and read with
    this request.

However, the server was only checking the requested region against the screen
bounds, allowing XGetImage requests to read pixels outside the bounds of a
window's ancestors.  Normally, this would just read other pixels from the
screen, but if one of the ancestor windows is redirected, the window's backing
pixmap may be smaller than the window itself.

This has a possibly unfortunate interaction with the SHAPE extension: a literal
interpretation of the language requires the GetImage request to be contained
entirely within the boundary of the window as defined by the SHAPE extension.
This change relaxes that slightly, allowing GetImage within the bounding box of
the SHAPE region.  However, if the SHAPE bounding box is smaller than the window
itself, this still results in a BadMatch if you try to GetImage the whole
window.
---
 dix/dispatch.c |   40 ++++++++++++++++++++++++++--------------
 1 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/dix/dispatch.c b/dix/dispatch.c
index 66f8f79..ea7a536 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -1926,24 +1926,36 @@ DoGetImage(ClientPtr client, int format, Drawable drawable,
 
     if(pDraw->type == DRAWABLE_WINDOW)
     {
-      if( /* check for being viewable */
-	 !((WindowPtr) pDraw)->realized ||
-	  /* check for being on screen */
-         pDraw->x + x < 0 ||
- 	 pDraw->x + x + width > pDraw->pScreen->width ||
-         pDraw->y + y < 0 ||
-         pDraw->y + y + height > pDraw->pScreen->height ||
-          /* check for being inside of border */
-         x < - wBorderWidth((WindowPtr)pDraw) ||
-         x + width > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width ||
-         y < -wBorderWidth((WindowPtr)pDraw) ||
-         y + height > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height
-        )
-	    return(BadMatch);
+	WindowPtr pWin = (WindowPtr)pDraw;
+	BoxPtr pBox;
+	int scrnx, scrny;
+
+	/* "If the drawable is a window, the window must be viewable ... or a
+	 * BadMatch error results" */
+	if (!pWin->viewable)
+	    return BadMatch;
+
+	/* "... and it must be the case that if there were no inferiors or
+	 *  overlapping windows, the specified rectangle of the window would be
+	 *  fully visible on the screen and wholly contained within the outside
+	 *  edges of the window, or a BadMatch error results."
+	 *
+	 * pWin->borderSize is clipped by parent windows but not inferior or
+	 * overlapping windows. */
+	scrnx = pDraw->x + x;
+	scrny = pDraw->y + y;
+
+	pBox = REGION_EXTENTS(pDraw->pScreen, &pWin->borderSize);
+	if (scrnx < pBox->x1 || scrnx + width > pBox->x2 ||
+	    scrny < pBox->y1 || scrny + height > pBox->y2)
+	    return BadMatch;
+
 	xgi.visual = wVisual (((WindowPtr) pDraw));
     }
     else
     {
+      /* "If the drawable is a pixmap, the given rectangle must be wholly
+       *  contained within the pixmap, or a BadMatch error results." */
       if(x < 0 ||
          x+width > (int)pDraw->width ||
          y < 0 ||
-- 
1.6.0.4



More information about the xorg-devel mailing list