diff options
author | Maarten Lankhorst <maarten.lankhorst@canonical.com> | 2013-01-08 11:00:33 +0100 |
---|---|---|
committer | Maarten Lankhorst <maarten.lankhorst@canonical.com> | 2013-01-08 11:01:44 +0100 |
commit | bade70ce71ea26fae4f250f0bd1729dfb0d392df (patch) | |
tree | c050b1ff51c7a8bfdfcf6c9dfa053e2c72a82ac5 /src/cir_shadow.c | |
parent | 5fcb3b018797457c3099a86c6c1257b6e4e89ceb (diff) |
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>
Diffstat (limited to 'src/cir_shadow.c')
-rw-r--r-- | src/cir_shadow.c | 317 |
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++; } } |