From 8ea762f94f4c942d898fdeb590a1630c83235c17 Mon Sep 17 00:00:00 2001
From: Tobias Stoeckmann <tobias@stoeckmann.org>
Date: Sun, 25 Sep 2016 21:25:25 +0200
Subject: Validation of server responses in XGetImage()

Check if enough bytes were received for specified image type and
geometry. Otherwise GetPixel and other functions could trigger an
out of boundary read later on.

CVE: CVE-2016-7942
Upstream-Status: Backport

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Reviewed-by: Matthieu Herrb <matthieu@herrb.eu>
Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>

diff --git a/src/GetImage.c b/src/GetImage.c
index c461abc..ff32d58 100644
--- a/src/GetImage.c
+++ b/src/GetImage.c
@@ -59,6 +59,7 @@ XImage *XGetImage (
 	char *data;
 	unsigned long nbytes;
 	XImage *image;
+	int planes;
 	LockDisplay(dpy);
 	GetReq (GetImage, req);
 	/*
@@ -91,18 +92,28 @@ XImage *XGetImage (
 	    return (XImage *) NULL;
 	}
         _XReadPad (dpy, data, nbytes);
-        if (format == XYPixmap)
-	   image = XCreateImage(dpy, _XVIDtoVisual(dpy, rep.visual),
-		  Ones (plane_mask &
-			(((unsigned long)0xFFFFFFFF) >> (32 - rep.depth))),
-		  format, 0, data, width, height, dpy->bitmap_pad, 0);
-	else /* format == ZPixmap */
-           image = XCreateImage (dpy, _XVIDtoVisual(dpy, rep.visual),
-		 rep.depth, ZPixmap, 0, data, width, height,
-		  _XGetScanlinePad(dpy, (int) rep.depth), 0);
+        if (format == XYPixmap) {
+	    image = XCreateImage(dpy, _XVIDtoVisual(dpy, rep.visual),
+		Ones (plane_mask &
+		    (((unsigned long)0xFFFFFFFF) >> (32 - rep.depth))),
+		format, 0, data, width, height, dpy->bitmap_pad, 0);
+	    planes = image->depth;
+	} else { /* format == ZPixmap */
+            image = XCreateImage (dpy, _XVIDtoVisual(dpy, rep.visual),
+		rep.depth, ZPixmap, 0, data, width, height,
+		    _XGetScanlinePad(dpy, (int) rep.depth), 0);
+	    planes = 1;
+	}
 
 	if (!image)
 	    Xfree(data);
+	if (planes < 1 || image->height < 1 || image->bytes_per_line < 1 ||
+	    INT_MAX / image->height <= image->bytes_per_line ||
+	    INT_MAX / planes <= image->height * image->bytes_per_line ||
+	    nbytes < planes * image->height * image->bytes_per_line) {
+	    XDestroyImage(image);
+	    image = NULL;
+	}
 	UnlockDisplay(dpy);
 	SyncHandle();
 	return (image);
-- 
cgit v0.10.2

