If driver fails to allocate memory for dri2 buffer server would crash
in send_buffers_reply.

Solution is to handle the allocation failure and return BadAlloc to
client.

Signed-off-by: Pauli Nieminen <[email protected]>
---
 hw/xfree86/dri2/dri2.c    |   69 +++++++++++++++++++++++++++++++++------------
 hw/xfree86/dri2/dri2ext.c |   13 ++++----
 2 files changed, 58 insertions(+), 24 deletions(-)

diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 03126b0..b1bd16b 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -329,6 +329,31 @@ allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr 
ds,
     }
 }
 
+static void
+update_dri2_drawable_buffers(DRI2DrawablePtr pPriv, DrawablePtr pDraw,
+                            DRI2BufferPtr *buffers, int *out_count, int 
*width, int *height)
+{
+    DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
+    int i;
+
+    if (pPriv->buffers != NULL) {
+       for (i = 0; i < pPriv->bufferCount; i++) {
+           if (pPriv->buffers[i] != NULL) {
+               (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
+           }
+       }
+
+       free(pPriv->buffers);
+    }
+
+    pPriv->buffers = buffers;
+    pPriv->bufferCount = *out_count;
+    pPriv->width = pDraw->width;
+    pPriv->height = pDraw->height;
+    *width = pPriv->width;
+    *height = pPriv->height;
+}
+
 static DRI2BufferPtr *
 do_get_buffers(DrawablePtr pDraw, int *width, int *height,
               unsigned int *attachments, int count, int *out_count,
@@ -366,6 +391,9 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
                                     &buffers[i]))
                buffers_changed = 1;
 
+       if (buffers[i] == NULL)
+           goto err_out;
+
        /* If the drawable is a window and the front-buffer is requested,
         * silently add the fake front-buffer to the list of requested
         * attachments.  The counting logic in the loop accounts for the case
@@ -398,6 +426,9 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
                                     front_format, dimensions_match,
                                     &buffers[i++]))
            buffers_changed = 1;
+
+       if (buffers[i] == NULL)
+           goto err_out;
     }
 
     if (need_fake_front > 0) {
@@ -406,29 +437,15 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
                                     &buffers[i++]))
            buffers_changed = 1;
 
+       if (buffers[i] == NULL)
+           goto err_out;
+
        have_fake_front = 1;
     }
 
     *out_count = i;
 
-
-    if (pPriv->buffers != NULL) {
-       for (i = 0; i < pPriv->bufferCount; i++) {
-           if (pPriv->buffers[i] != NULL) {
-               (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
-           }
-       }
-
-       free(pPriv->buffers);
-    }
-
-    pPriv->buffers = buffers;
-    pPriv->bufferCount = *out_count;
-    pPriv->width = pDraw->width;
-    pPriv->height = pDraw->height;
-    *width = pPriv->width;
-    *height = pPriv->height;
-
+    update_dri2_drawable_buffers(pPriv, pDraw, buffers, out_count, width, 
height);
 
     /* If the client is getting a fake front-buffer, pre-fill it with the
      * contents of the real front-buffer.  This ensures correct operation of
@@ -449,6 +466,22 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
     }
 
     return pPriv->buffers;
+
+err_out:
+
+    *out_count = 0;
+
+    for (i = 0; i < count; i++) {
+           if (buffers[i] != NULL)
+                   (*ds->DestroyBuffer)(pDraw, buffers[i]);
+    }
+
+    free(buffers);
+    buffers = NULL;
+
+    update_dri2_drawable_buffers(pPriv, pDraw, buffers, out_count, width, 
height);
+
+    return buffers;
 }
 
 DRI2BufferPtr *
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
index dd456d7..37d042b 100644
--- a/hw/xfree86/dri2/dri2ext.c
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -206,7 +206,7 @@ ProcDRI2DestroyDrawable(ClientPtr client)
 }
 
 
-static void
+static int
 send_buffers_reply(ClientPtr client, DrawablePtr pDrawable,
                   DRI2BufferPtr *buffers, int count, int width, int height)
 {
@@ -214,6 +214,9 @@ send_buffers_reply(ClientPtr client, DrawablePtr pDrawable,
     int skip = 0;
     int i;
 
+    if (buffers == NULL)
+           return BadAlloc;
+
     if (pDrawable->type == DRAWABLE_WINDOW) {
        for (i = 0; i < count; i++) {
            /* Do not send the real front buffer of a window to the client.
@@ -250,6 +253,7 @@ send_buffers_reply(ClientPtr client, DrawablePtr pDrawable,
        buffer.flags = buffers[i]->flags;
        WriteToClient(client, sizeof(xDRI2Buffer), &buffer);
     }
+    return Success;
 }
 
 
@@ -275,9 +279,8 @@ ProcDRI2GetBuffers(ClientPtr client)
                             attachments, stuff->count, &count);
 
 
-    send_buffers_reply(client, pDrawable, buffers, count, width, height);
+    return send_buffers_reply(client, pDrawable, buffers, count, width, 
height);
 
-    return Success;
 }
 
 static int
@@ -301,9 +304,7 @@ ProcDRI2GetBuffersWithFormat(ClientPtr client)
     buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height,
                                       attachments, stuff->count, &count);
 
-    send_buffers_reply(client, pDrawable, buffers, count, width, height);
-
-    return Success;
+    return send_buffers_reply(client, pDrawable, buffers, count, width, 
height);
 }
 
 static int
-- 
1.6.3.3

_______________________________________________
[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