summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaarten Lankhorst <maarten.lankhorst@canonical.com>2013-01-08 11:00:33 +0100
committerMaarten Lankhorst <maarten.lankhorst@canonical.com>2013-01-08 11:01:44 +0100
commitbade70ce71ea26fae4f250f0bd1729dfb0d392df (patch)
treec050b1ff51c7a8bfdfcf6c9dfa053e2c72a82ac5
parent5fcb3b018797457c3099a86c6c1257b6e4e89ceb (diff)
downloadxorg-driver-xf86-video-cirrus-bade70ce71ea26fae4f250f0bd1729dfb0d392df.tar.gz
cirrus: fix out of bounds access to shadowfb
Perform the same bounds checking other drivers do. Thanks to Dave Gilbert for feedback on this patch. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
-rw-r--r--src/cir_shadow.c317
1 files changed, 180 insertions, 137 deletions
diff --git a/src/cir_shadow.c b/src/cir_shadow.c
index a9b425b..6bde0fd 100644
--- a/src/cir_shadow.c
+++ b/src/cir_shadow.c
@@ -15,30 +15,41 @@
#include "cir.h"
#include "alp.h"
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
_X_EXPORT void
cirRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
{
CirPtr pCir = CIRPTR(pScrn);
- int width, height, Bpp, FBPitch;
+ int width, height, Bpp, FBPitch, x1, x2, y1, y2;
unsigned char *src, *dst;
Bpp = pScrn->bitsPerPixel >> 3;
FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel);
while(num--) {
- width = (pbox->x2 - pbox->x1) * Bpp;
- height = pbox->y2 - pbox->y1;
- src = pCir->ShadowPtr + (pbox->y1 * pCir->ShadowPitch) +
- (pbox->x1 * Bpp);
- dst = pCir->FbBase + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp);
-
- while(height--) {
- memcpy(dst, src, width);
- dst += FBPitch;
- src += pCir->ShadowPitch;
- }
-
- pbox++;
+ x1 = MAX(pbox->x1, 0);
+ y1 = MAX(pbox->y1, 0);
+ x2 = MIN(pbox->x2, pScrn->virtualX);
+ y2 = MIN(pbox->y2, pScrn->virtualY);
+
+ width = (x2 - x1) * Bpp;
+ height = y2 - y1;
+
+ if (width <= 0 || height <= 0)
+ continue;
+
+ src = pCir->ShadowPtr + (y1 * pCir->ShadowPitch) + (x1 * Bpp);
+ dst = pCir->FbBase + (y1 * FBPitch) + (x1 * Bpp);
+
+ while(height--) {
+ memcpy(dst, src, width);
+ dst += FBPitch;
+ src += pCir->ShadowPitch;
+ }
+
+ pbox++;
}
}
@@ -64,7 +75,7 @@ _X_EXPORT void
cirRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
{
CirPtr pCir = CIRPTR(pScrn);
- int count, width, height, y1, y2, dstPitch, srcPitch;
+ int count, width, height, x1, x2, y1, y2, dstPitch, srcPitch;
CARD8 *dstPtr, *srcPtr, *src;
CARD32 *dst;
@@ -72,36 +83,44 @@ cirRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
srcPitch = -pCir->rotate * pCir->ShadowPitch;
while(num--) {
- width = pbox->x2 - pbox->x1;
- y1 = pbox->y1 & ~3;
- y2 = (pbox->y2 + 3) & ~3;
- height = (y2 - y1) >> 2; /* in dwords */
-
- if(pCir->rotate == 1) {
- dstPtr = pCir->FbBase +
- (pbox->x1 * dstPitch) + pScrn->virtualX - y2;
- srcPtr = pCir->ShadowPtr + ((1 - y2) * srcPitch) + pbox->x1;
- } else {
- dstPtr = pCir->FbBase +
- ((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
- srcPtr = pCir->ShadowPtr + (y1 * srcPitch) + pbox->x2 - 1;
- }
-
- while(width--) {
- src = srcPtr;
- dst = (CARD32*)dstPtr;
- count = height;
- while(count--) {
- *(dst++) = src[0] | (src[srcPitch] << 8) |
- (src[srcPitch * 2] << 16) |
- (src[srcPitch * 3] << 24);
- src += srcPitch * 4;
- }
- srcPtr += pCir->rotate;
- dstPtr += dstPitch;
- }
-
- pbox++;
+ x1 = MAX(pbox->x1, 0);
+ y1 = MAX(pbox->y1, 0);
+ x2 = MIN(pbox->x2, pScrn->virtualX);
+ y2 = MIN(pbox->y2, pScrn->virtualY);
+
+ width = x2 - x1;
+ y1 = y1 & ~3;
+ y2 = (y2 + 3) & ~3;
+ height = (y2 - y1) / 4; /* in dwords */
+
+ if (width <= 0 || height <= 0)
+ continue;
+
+ if(pCir->rotate == 1) {
+ dstPtr = pCir->FbBase +
+ (x1 * dstPitch) + pScrn->virtualX - y2;
+ srcPtr = pCir->ShadowPtr + ((1 - y2) * srcPitch) + x1;
+ } else {
+ dstPtr = pCir->FbBase +
+ ((pScrn->virtualY - x2) * dstPitch) + y1;
+ srcPtr = pCir->ShadowPtr + (y1 * srcPitch) + x2 - 1;
+ }
+
+ while(width--) {
+ src = srcPtr;
+ dst = (CARD32*)dstPtr;
+ count = height;
+ while(count--) {
+ *(dst++) = src[0] | (src[srcPitch] << 8) |
+ (src[srcPitch * 2] << 16) |
+ (src[srcPitch * 3] << 24);
+ src += srcPitch * 4;
+ }
+ srcPtr += pCir->rotate;
+ dstPtr += dstPitch;
+ }
+
+ pbox++;
}
}
@@ -110,7 +129,7 @@ _X_EXPORT void
cirRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
{
CirPtr pCir = CIRPTR(pScrn);
- int count, width, height, y1, y2, dstPitch, srcPitch;
+ int count, width, height, x1, x2, y1, y2, dstPitch, srcPitch;
CARD16 *dstPtr, *srcPtr, *src;
CARD32 *dst;
@@ -118,36 +137,44 @@ cirRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
srcPitch = -pCir->rotate * pCir->ShadowPitch >> 1;
while(num--) {
- width = pbox->x2 - pbox->x1;
- y1 = pbox->y1 & ~1;
- y2 = (pbox->y2 + 1) & ~1;
- height = (y2 - y1) >> 1; /* in dwords */
-
- if(pCir->rotate == 1) {
- dstPtr = (CARD16*)pCir->FbBase +
- (pbox->x1 * dstPitch) + pScrn->virtualX - y2;
- srcPtr = (CARD16*)pCir->ShadowPtr +
- ((1 - y2) * srcPitch) + pbox->x1;
- } else {
- dstPtr = (CARD16*)pCir->FbBase +
- ((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
- srcPtr = (CARD16*)pCir->ShadowPtr +
- (y1 * srcPitch) + pbox->x2 - 1;
- }
-
- while(width--) {
- src = srcPtr;
- dst = (CARD32*)dstPtr;
- count = height;
- while(count--) {
- *(dst++) = src[0] | (src[srcPitch] << 16);
- src += srcPitch * 2;
- }
- srcPtr += pCir->rotate;
- dstPtr += dstPitch;
- }
-
- pbox++;
+ x1 = MAX(pbox->x1, 0);
+ y1 = MAX(pbox->y1, 0);
+ x2 = MIN(pbox->x2, pScrn->virtualX);
+ y2 = MIN(pbox->y2, pScrn->virtualY);
+
+ width = x2 - x1;
+ y1 = y1 & ~1;
+ y2 = (y2 + 1) & ~1;
+ height = (y2 - y1) / 2; /* in dwords */
+
+ if (width <= 0 || height <= 0)
+ continue;
+
+ if(pCir->rotate == 1) {
+ dstPtr = (CARD16*)pCir->FbBase +
+ (x1 * dstPitch) + pScrn->virtualX - y2;
+ srcPtr = (CARD16*)pCir->ShadowPtr +
+ ((1 - y2) * srcPitch) + x1;
+ } else {
+ dstPtr = (CARD16*)pCir->FbBase +
+ ((pScrn->virtualY - x2) * dstPitch) + y1;
+ srcPtr = (CARD16*)pCir->ShadowPtr +
+ (y1 * srcPitch) + x2 - 1;
+ }
+
+ while(width--) {
+ src = srcPtr;
+ dst = (CARD32*)dstPtr;
+ count = height;
+ while(count--) {
+ *(dst++) = src[0] | (src[srcPitch] << 16);
+ src += srcPitch * 2;
+ }
+ srcPtr += pCir->rotate;
+ dstPtr += dstPitch;
+ }
+
+ pbox++;
}
}
@@ -157,7 +184,7 @@ _X_EXPORT void
cirRefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
{
CirPtr pCir = CIRPTR(pScrn);
- int count, width, height, y1, y2, dstPitch, srcPitch;
+ int count, width, height, x1, x2, y1, y2, dstPitch, srcPitch;
CARD8 *dstPtr, *srcPtr, *src;
CARD32 *dst;
@@ -165,42 +192,50 @@ cirRefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
srcPitch = -pCir->rotate * pCir->ShadowPitch;
while(num--) {
- width = pbox->x2 - pbox->x1;
- y1 = pbox->y1 & ~3;
- y2 = (pbox->y2 + 3) & ~3;
- height = (y2 - y1) >> 2; /* blocks of 3 dwords */
-
- if(pCir->rotate == 1) {
- dstPtr = pCir->FbBase +
- (pbox->x1 * dstPitch) + ((pScrn->virtualX - y2) * 3);
- srcPtr = pCir->ShadowPtr + ((1 - y2) * srcPitch) + (pbox->x1 * 3);
- } else {
- dstPtr = pCir->FbBase +
- ((pScrn->virtualY - pbox->x2) * dstPitch) + (y1 * 3);
- srcPtr = pCir->ShadowPtr + (y1 * srcPitch) + (pbox->x2 * 3) - 3;
- }
-
- while(width--) {
- src = srcPtr;
- dst = (CARD32*)dstPtr;
- count = height;
- while(count--) {
- dst[0] = src[0] | (src[1] << 8) | (src[2] << 16) |
+ x1 = MAX(pbox->x1, 0);
+ y1 = MAX(pbox->y1, 0);
+ x2 = MIN(pbox->x2, pScrn->virtualX);
+ y2 = MIN(pbox->y2, pScrn->virtualY);
+
+ width = x2 - x1;
+ y1 = y1 & ~3;
+ y2 = (y2 + 3) & ~3;
+ height = (y2 - y1) / 4; /* blocks of 3 dwords */
+
+ if (width <= 0 || height <= 0)
+ continue;
+
+ if(pCir->rotate == 1) {
+ dstPtr = pCir->FbBase +
+ (x1 * dstPitch) + ((pScrn->virtualX - y2) * 3);
+ srcPtr = pCir->ShadowPtr + ((1 - y2) * srcPitch) + (x1 * 3);
+ } else {
+ dstPtr = pCir->FbBase +
+ ((pScrn->virtualY - x2) * dstPitch) + (y1 * 3);
+ srcPtr = pCir->ShadowPtr + (y1 * srcPitch) + (x2 * 3) - 3;
+ }
+
+ while(width--) {
+ src = srcPtr;
+ dst = (CARD32*)dstPtr;
+ count = height;
+ while(count--) {
+ dst[0] = src[0] | (src[1] << 8) | (src[2] << 16) |
(src[srcPitch] << 24);
- dst[1] = src[srcPitch + 1] | (src[srcPitch + 2] << 8) |
+ dst[1] = src[srcPitch + 1] | (src[srcPitch + 2] << 8) |
(src[srcPitch * 2] << 16) |
(src[(srcPitch * 2) + 1] << 24);
- dst[2] = src[(srcPitch * 2) + 2] | (src[srcPitch * 3] << 8) |
+ dst[2] = src[(srcPitch * 2) + 2] | (src[srcPitch * 3] << 8) |
(src[(srcPitch * 3) + 1] << 16) |
(src[(srcPitch * 3) + 2] << 24);
- dst += 3;
- src += srcPitch * 4;
- }
- srcPtr += pCir->rotate * 3;
- dstPtr += dstPitch;
- }
-
- pbox++;
+ dst += 3;
+ src += srcPitch * 4;
+ }
+ srcPtr += pCir->rotate * 3;
+ dstPtr += dstPitch;
+ }
+
+ pbox++;
}
}
@@ -208,41 +243,49 @@ _X_EXPORT void
cirRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
{
CirPtr pCir = CIRPTR(pScrn);
- int count, width, height, dstPitch, srcPitch;
+ int count, width, height, x1, x2, y1, y2, dstPitch, srcPitch;
CARD32 *dstPtr, *srcPtr, *src, *dst;
dstPitch = pScrn->displayWidth;
srcPitch = -pCir->rotate * pCir->ShadowPitch >> 2;
while(num--) {
- width = pbox->x2 - pbox->x1;
- height = pbox->y2 - pbox->y1;
-
- if(pCir->rotate == 1) {
- dstPtr = (CARD32*)pCir->FbBase +
- (pbox->x1 * dstPitch) + pScrn->virtualX - pbox->y2;
- srcPtr = (CARD32*)pCir->ShadowPtr +
- ((1 - pbox->y2) * srcPitch) + pbox->x1;
- } else {
- dstPtr = (CARD32*)pCir->FbBase +
- ((pScrn->virtualY - pbox->x2) * dstPitch) + pbox->y1;
- srcPtr = (CARD32*)pCir->ShadowPtr +
- (pbox->y1 * srcPitch) + pbox->x2 - 1;
- }
-
- while(width--) {
- src = srcPtr;
- dst = dstPtr;
- count = height;
- while(count--) {
- *(dst++) = *src;
- src += srcPitch;
- }
- srcPtr += pCir->rotate;
- dstPtr += dstPitch;
- }
-
- pbox++;
+ x1 = MAX(pbox->x1, 0);
+ y1 = MAX(pbox->y1, 0);
+ x2 = MIN(pbox->x2, pScrn->virtualX);
+ y2 = MIN(pbox->y2, pScrn->virtualY);
+
+ width = x2 - x1;
+ height = y2 - y1;
+
+ if (width <= 0 || height <= 0)
+ continue;
+
+ if(pCir->rotate == 1) {
+ dstPtr = (CARD32*)pCir->FbBase +
+ (x1 * dstPitch) + pScrn->virtualX - y2;
+ srcPtr = (CARD32*)pCir->ShadowPtr +
+ ((1 - y2) * srcPitch) + x1;
+ } else {
+ dstPtr = (CARD32*)pCir->FbBase +
+ ((pScrn->virtualY - x2) * dstPitch) + y1;
+ srcPtr = (CARD32*)pCir->ShadowPtr +
+ (y1 * srcPitch) + x2 - 1;
+ }
+
+ while(width--) {
+ src = srcPtr;
+ dst = dstPtr;
+ count = height;
+ while(count--) {
+ *(dst++) = *src;
+ src += srcPitch;
+ }
+ srcPtr += pCir->rotate;
+ dstPtr += dstPitch;
+ }
+
+ pbox++;
}
}