dix: integer overflow in RegionSizeof() [CVE-2014-8092 3/4]

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>
This commit is contained in:
Alan Coopersmith 2014-01-22 22:37:15 -08:00
parent bc8e20430b
commit 97015a07b9
2 changed files with 20 additions and 10 deletions

View File

@ -169,7 +169,6 @@ Equipment Corporation.
((r1)->y1 <= (r2)->y1) && \ ((r1)->y1 <= (r2)->y1) && \
((r1)->y2 >= (r2)->y2) ) ((r1)->y2 >= (r2)->y2) )
#define xallocData(n) malloc(RegionSizeof(n))
#define xfreeData(reg) if ((reg)->data && (reg)->data->size) free((reg)->data) #define xfreeData(reg) if ((reg)->data && (reg)->data->size) free((reg)->data)
#define RECTALLOC_BAIL(pReg,n,bail) \ #define RECTALLOC_BAIL(pReg,n,bail) \
@ -205,8 +204,9 @@ if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
#define DOWNSIZE(reg,numRects) \ #define DOWNSIZE(reg,numRects) \
if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \ if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \
{ \ { \
RegDataPtr NewData; \ size_t NewSize = RegionSizeof(numRects); \
NewData = (RegDataPtr)realloc((reg)->data, RegionSizeof(numRects)); \ RegDataPtr NewData = \
(NewSize > 0) ? realloc((reg)->data, NewSize) : NULL ; \
if (NewData) \ if (NewData) \
{ \ { \
NewData->size = (numRects); \ NewData->size = (numRects); \
@ -345,17 +345,20 @@ Bool
RegionRectAlloc(RegionPtr pRgn, int n) RegionRectAlloc(RegionPtr pRgn, int n)
{ {
RegDataPtr data; RegDataPtr data;
size_t rgnSize;
if (!pRgn->data) { if (!pRgn->data) {
n++; n++;
pRgn->data = xallocData(n); rgnSize = RegionSizeof(n);
pRgn->data = (rgnSize > 0) ? malloc(rgnSize) : NULL;
if (!pRgn->data) if (!pRgn->data)
return RegionBreak(pRgn); return RegionBreak(pRgn);
pRgn->data->numRects = 1; pRgn->data->numRects = 1;
*RegionBoxptr(pRgn) = pRgn->extents; *RegionBoxptr(pRgn) = pRgn->extents;
} }
else if (!pRgn->data->size) { else if (!pRgn->data->size) {
pRgn->data = xallocData(n); rgnSize = RegionSizeof(n);
pRgn->data = (rgnSize > 0) ? malloc(rgnSize) : NULL;
if (!pRgn->data) if (!pRgn->data)
return RegionBreak(pRgn); return RegionBreak(pRgn);
pRgn->data->numRects = 0; pRgn->data->numRects = 0;
@ -367,7 +370,8 @@ RegionRectAlloc(RegionPtr pRgn, int n)
n = 250; n = 250;
} }
n += pRgn->data->numRects; n += pRgn->data->numRects;
data = (RegDataPtr) realloc(pRgn->data, RegionSizeof(n)); rgnSize = RegionSizeof(n);
data = (rgnSize > 0) ? realloc(pRgn->data, rgnSize) : NULL;
if (!data) if (!data)
return RegionBreak(pRgn); return RegionBreak(pRgn);
pRgn->data = data; pRgn->data = data;
@ -1312,6 +1316,7 @@ RegionFromRects(int nrects, xRectangle *prect, int ctype)
{ {
RegionPtr pRgn; RegionPtr pRgn;
size_t rgnSize;
RegDataPtr pData; RegDataPtr pData;
BoxPtr pBox; BoxPtr pBox;
int i; int i;
@ -1338,7 +1343,8 @@ RegionFromRects(int nrects, xRectangle *prect, int ctype)
} }
return pRgn; return pRgn;
} }
pData = xallocData(nrects); rgnSize = RegionSizeof(nrects);
pData = (rgnSize > 0) ? malloc(rgnSize) : NULL;
if (!pData) { if (!pData) {
RegionBreak(pRgn); RegionBreak(pRgn);
return pRgn; return pRgn;

View File

@ -127,7 +127,10 @@ RegionEnd(RegionPtr reg)
static inline size_t static inline size_t
RegionSizeof(size_t n) RegionSizeof(size_t 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 static inline void
@ -138,9 +141,10 @@ RegionInit(RegionPtr _pReg, BoxPtr _rect, int _size)
(_pReg)->data = (RegDataPtr) NULL; (_pReg)->data = (RegDataPtr) NULL;
} }
else { else {
size_t rgnSize;
(_pReg)->extents = RegionEmptyBox; (_pReg)->extents = RegionEmptyBox;
if (((_size) > 1) && ((_pReg)->data = if (((_size) > 1) && ((rgnSize = RegionSizeof(_size)) > 0) &&
(RegDataPtr) malloc(RegionSizeof(_size)))) { (((_pReg)->data = malloc(rgnSize)) != NULL)) {
(_pReg)->data->size = (_size); (_pReg)->data->size = (_size);
(_pReg)->data->numRects = 0; (_pReg)->data->numRects = 0;
} }