Fixes:

  Bug 27313 - random X11 crash (SIGSEGV) when rendering firefox in pixman/intel
  https://bugs.freedesktop.org/show_bug.cgi?id=27313

As pixman does not guard against a fill request outside of the buffer,
we must be be careful and trim oversized fills.

Signed-off-by: Chris Wilson <[email protected]>
Tested-by: Michael Stapelberg <[email protected]>
---
 fb/fbfill.c    |   38 ++++++++++++++++++++++++--------------
 include/misc.h |    1 +
 2 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/fb/fbfill.c b/fb/fbfill.c
index 801a0d0..e76dcf1 100644
--- a/fb/fbfill.c
+++ b/fb/fbfill.c
@@ -39,20 +39,31 @@ fbFill (DrawablePtr pDrawable,
     int                    dstBpp;
     int                    dstXoff, dstYoff;
     FbGCPrivPtr            pPriv = fbGetGCPrivate(pGC);
-    
+    int x1, x2, y1, y2;
+
     fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
 
+    /* trim fill to drawable bounds */
+    x1 = clamp(x + dstXoff,         0, pDrawable->width);
+    x2 = clamp(x + dstXoff + width, 0, pDrawable->width);
+
+    y1 = clamp(y + dstYoff,          0, pDrawable->height);
+    y2 = clamp(y + dstYoff + height, 0, pDrawable->height);
+
+    width  = x2 - x1;
+    height = y2 - y1;
+
     switch (pGC->fillStyle) {
     case FillSolid:
 #ifndef FB_ACCESS_WRAPPER
        if (pPriv->and || !pixman_fill ((uint32_t *)dst, dstStride, dstBpp,
-                                       x + dstXoff, y + dstYoff,
+                                       x1, y1,
                                        width, height,
                                        pPriv->xor))
 #endif     
-           fbSolid (dst + (y + dstYoff) * dstStride, 
-                    dstStride, 
-                    (x + dstXoff) * dstBpp,
+           fbSolid (dst + y1 * dstStride,
+                    dstStride,
+                    x1 * dstBpp,
                     dstBpp,
                     width * dstBpp, height,
                     pPriv->and, pPriv->xor);
@@ -76,9 +87,9 @@ fbFill (DrawablePtr pDrawable,
            else
                alu = FbOpaqueStipple1Rop(pGC->alu,pGC->fgPixel,pGC->bgPixel);
            fbGetDrawable (&pStip->drawable, stip, stipStride, stipBpp, 
stipXoff, stipYoff);
-           fbTile (dst + (y + dstYoff) * dstStride,
+           fbTile (dst + y1 * dstStride,
                    dstStride,
-                   x + dstXoff,
+                   x1,
                    width, height,
                    stip,
                    stipStride,
@@ -87,7 +98,6 @@ fbFill (DrawablePtr pDrawable,
                    alu,
                    pPriv->pm,
                    dstBpp,
-                   
                    (pGC->patOrg.x + pDrawable->x + dstXoff),
                    pGC->patOrg.y + pDrawable->y - y);
            fbFinishAccess (&pStip->drawable);
@@ -114,9 +124,9 @@ fbFill (DrawablePtr pDrawable,
            }
 
            fbGetStipDrawable (&pStip->drawable, stip, stipStride, stipBpp, 
stipXoff, stipYoff);
-           fbStipple (dst + (y + dstYoff) * dstStride, 
-                      dstStride, 
-                      (x + dstXoff) * dstBpp,
+           fbStipple (dst + y1 * dstStride,
+                      dstStride,
+                      x1 * dstBpp,
                       dstBpp,
                       width * dstBpp, height,
                       stip,
@@ -144,9 +154,9 @@ fbFill (DrawablePtr pDrawable,
        fbGetDrawable (&pTile->drawable, tile, tileStride, tileBpp, tileXoff, 
tileYoff);
        tileWidth = pTile->drawable.width;
        tileHeight = pTile->drawable.height;
-       fbTile (dst + (y + dstYoff) * dstStride, 
-               dstStride, 
-               (x + dstXoff) * dstBpp, 
+       fbTile (dst + y1 * dstStride,
+               dstStride,
+               x1 * dstBpp,
                width * dstBpp, height,
                tile,
                tileStride,
diff --git a/include/misc.h b/include/misc.h
index 62d813e..595d4e0 100644
--- a/include/misc.h
+++ b/include/misc.h
@@ -136,6 +136,7 @@ typedef struct _xReq *xReqPtr;
 
 #define min(a, b) (((a) < (b)) ? (a) : (b))
 #define max(a, b) (((a) > (b)) ? (a) : (b))
+#define clamp(v, a, b) (((v) < (a)) ? (a) : (v) > (b) ? (b) : (v))
 /* abs() is a function, not a macro; include the file declaring
  * it in case we haven't done that yet.
  */
-- 
1.7.1

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to