Subject: dix: integer overflow in RegionSizeof()
References: bnc#907268, CVE-2014-8092
Patch-Mainline: Upstream
Signed-off-by: Michal Srb <msrb@suse.com>

RegionSizeof contains several integer overflows if a large length
value is passed in.  Once we fix it to return 0 on overflow, we
also have to fix the callers to handle this error condition

v2: Fixed limit calculation in RegionSizeof as pointed out by jcristau.

Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Julien Cristau <jcristau@debian.org>
---
 dix/region.c        |   20 +++++++++++++-------
 include/regionstr.h |   10 +++++++---
 2 files changed, 20 insertions(+), 10 deletions(-)

Index: xorg-server-1.15.2/dix/region.c
===================================================================
--- xorg-server-1.15.2.orig/dix/region.c
+++ xorg-server-1.15.2/dix/region.c
@@ -169,7 +169,6 @@ Equipment Corporation.
         ((r1)->y1 <= (r2)->y1) && \
         ((r1)->y2 >= (r2)->y2) )
 
-#define xallocData(n) malloc(RegionSizeof(n))
 #define xfreeData(reg) if ((reg)->data && (reg)->data->size) free((reg)->data)
 
 #define RECTALLOC_BAIL(pReg,n,bail) \
@@ -205,8 +204,9 @@ if (!(pReg)->data || (((pReg)->data->num
 #define DOWNSIZE(reg,numRects)						 \
 if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \
 {									 \
-    RegDataPtr NewData;							 \
-    NewData = (RegDataPtr)realloc((reg)->data, RegionSizeof(numRects));	 \
+    size_t NewSize = RegionSizeof(numRects);				 \
+    RegDataPtr NewData =						 \
+        (NewSize > 0) ? realloc((reg)->data, NewSize) : NULL ;		 \
     if (NewData)							 \
     {									 \
 	NewData->size = (numRects);					 \
@@ -345,17 +345,20 @@ Bool
 RegionRectAlloc(RegionPtr pRgn, int n)
 {
     RegDataPtr data;
+    size_t rgnSize;
 
     if (!pRgn->data) {
         n++;
-        pRgn->data = xallocData(n);
+        rgnSize = RegionSizeof(n);
+        pRgn->data = (rgnSize > 0) ? malloc(rgnSize) : NULL;
         if (!pRgn->data)
             return RegionBreak(pRgn);
         pRgn->data->numRects = 1;
         *RegionBoxptr(pRgn) = pRgn->extents;
     }
     else if (!pRgn->data->size) {
-        pRgn->data = xallocData(n);
+        rgnSize = RegionSizeof(n);
+        pRgn->data = (rgnSize > 0) ? malloc(rgnSize) : NULL;
         if (!pRgn->data)
             return RegionBreak(pRgn);
         pRgn->data->numRects = 0;
@@ -367,7 +370,8 @@ RegionRectAlloc(RegionPtr pRgn, int n)
                 n = 250;
         }
         n += pRgn->data->numRects;
-        data = (RegDataPtr) realloc(pRgn->data, RegionSizeof(n));
+        rgnSize = RegionSizeof(n);
+        data = (rgnSize > 0) ? realloc(pRgn->data, rgnSize) : NULL;
         if (!data)
             return RegionBreak(pRgn);
         pRgn->data = data;
@@ -1312,6 +1316,7 @@ RegionFromRects(int nrects, xRectangle *
 {
 
     RegionPtr pRgn;
+    size_t rgnSize;
     RegDataPtr pData;
     BoxPtr pBox;
     int i;
@@ -1338,7 +1343,8 @@ RegionFromRects(int nrects, xRectangle *
         }
         return pRgn;
     }
-    pData = xallocData(nrects);
+    rgnSize = RegionSizeof(nrects);
+    pData = (rgnSize > 0) ? malloc(rgnSize) : NULL;
     if (!pData) {
         RegionBreak(pRgn);
         return pRgn;
Index: xorg-server-1.15.2/include/regionstr.h
===================================================================
--- xorg-server-1.15.2.orig/include/regionstr.h
+++ xorg-server-1.15.2/include/regionstr.h
@@ -127,7 +127,10 @@ RegionEnd(RegionPtr reg)
 static inline size_t
 RegionSizeof(int n)
 {
-    return (sizeof(RegDataRec) + ((n) * sizeof(BoxRec)));
+    if (n < ((INT_MAX - sizeof(RegDataRec)) / sizeof(BoxRec)))
+        return (sizeof(RegDataRec) + ((n) * sizeof(BoxRec)));
+    else
+        return 0;
 }
 
 static inline void
@@ -138,9 +141,10 @@ RegionInit(RegionPtr _pReg, BoxPtr _rect
         (_pReg)->data = (RegDataPtr) NULL;
     }
     else {
+        size_t rgnSize;
         (_pReg)->extents = RegionEmptyBox;
-        if (((_size) > 1) && ((_pReg)->data =
-                              (RegDataPtr) malloc(RegionSizeof(_size)))) {
+        if (((_size) > 1) && ((rgnSize = RegionSizeof(_size)) > 0) &&
+            (((_pReg)->data = malloc(rgnSize)) != NULL)) {
             (_pReg)->data->size = (_size);
             (_pReg)->data->numRects = 0;
         }
