Fixed double free for uwac buffers
authorakallabeth <akallabeth@posteo.net>
Tue, 16 Jun 2020 11:54:12 +0000 (13:54 +0200)
committerArmin Novak <armin.novak@thincast.com>
Mon, 22 Jun 2020 07:30:36 +0000 (09:30 +0200)
(cherry picked from commit 1bc48b058f013a8c88db2a1d7da2ad25dcd3bc4c)

uwac/libuwac/uwac-priv.h
uwac/libuwac/uwac-window.c

index 75ad6e0..2ef073d 100644 (file)
@@ -235,7 +235,8 @@ struct uwac_window
 
        struct wl_region* opaque_region;
        struct wl_region* input_region;
-       UwacBuffer *drawingBuffer, *pendingBuffer;
+       SSIZE_T drawingBufferIdx;
+       SSIZE_T pendingBufferIdx;
        struct wl_surface* surface;
        struct wl_shell_surface* shell_surface;
        struct xdg_surface* xdg_surface;
index f76d43b..2f424e8 100644 (file)
@@ -136,13 +136,13 @@ static void xdg_handle_toplevel_configure(void* data, struct xdg_toplevel* xdg_t
                {
                        assert(
                            uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
-                       window->drawingBuffer = window->pendingBuffer = NULL;
+                       window->drawingBufferIdx = window->pendingBufferIdx = -1;
                        return;
                }
 
-               window->drawingBuffer = &window->buffers[0];
-               if (window->pendingBuffer != NULL)
-                       window->pendingBuffer = window->drawingBuffer;
+               window->drawingBufferIdx = 0;
+               if (window->pendingBufferIdx != -1)
+                       window->pendingBufferIdx = window->drawingBufferIdx;
        }
        else
        {
@@ -219,13 +219,13 @@ static void ivi_handle_configure(void* data, struct ivi_surface* surface, int32_
                {
                        assert(
                            uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
-                       window->drawingBuffer = window->pendingBuffer = NULL;
+                       window->drawingBufferIdx = window->pendingBufferIdx = -1;
                        return;
                }
 
-               window->drawingBuffer = &window->buffers[0];
-               if (window->pendingBuffer != NULL)
-                       window->pendingBuffer = window->drawingBuffer;
+               window->drawingBufferIdx = 0;
+               if (window->pendingBufferIdx != -1)
+                       window->pendingBufferIdx = window->drawingBufferIdx;
        }
        else
        {
@@ -277,13 +277,13 @@ static void shell_configure(void* data, struct wl_shell_surface* surface, uint32
                {
                        assert(
                            uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
-                       window->drawingBuffer = window->pendingBuffer = NULL;
+                       window->drawingBufferIdx = window->pendingBufferIdx = -1;
                        return;
                }
 
-               window->drawingBuffer = &window->buffers[0];
-               if (window->pendingBuffer != NULL)
-                       window->pendingBuffer = window->drawingBuffer;
+               window->drawingBufferIdx = 0;
+               if (window->pendingBufferIdx != -1)
+                       window->pendingBufferIdx = window->drawingBufferIdx;
        }
        else
        {
@@ -364,15 +364,21 @@ error_mmap:
        return ret;
 }
 
-static UwacBuffer* UwacWindowFindFreeBuffer(UwacWindow* w)
+static UwacBuffer* UwacWindowFindFreeBuffer(UwacWindow* w, SSIZE_T* index)
 {
-       int i, ret;
+       SSIZE_T i;
+       int ret;
+
+       if (index)
+               *index = -1;
 
        for (i = 0; i < w->nbuffers; i++)
        {
                if (!w->buffers[i].used)
                {
                        w->buffers[i].used = true;
+                       if (index)
+                               *index = i;
                        return &w->buffers[i];
                }
        }
@@ -386,6 +392,8 @@ static UwacBuffer* UwacWindowFindFreeBuffer(UwacWindow* w)
        }
 
        w->buffers[i].used = true;
+       if (index)
+               *index = i;
        return &w->buffers[i];
 }
 
@@ -457,7 +465,8 @@ UwacWindow* UwacCreateWindowShm(UwacDisplay* display, uint32_t width, uint32_t h
        }
 
        w->buffers[0].used = true;
-       w->drawingBuffer = &w->buffers[0];
+       w->drawingBufferIdx = 0;
+       w->pendingBufferIdx = -1;
        w->surface = wl_compositor_create_surface(display->compositor);
 
        if (!w->surface)
@@ -603,7 +612,16 @@ UwacReturnCode UwacWindowSetInputRegion(UwacWindow* window, uint32_t x, uint32_t
 
 void* UwacWindowGetDrawingBuffer(UwacWindow* window)
 {
-       return window->drawingBuffer->data;
+       UwacBuffer* buffer;
+
+       if (window->drawingBufferIdx < 0)
+               return NULL;
+
+       buffer = &window->buffers[window->drawingBufferIdx];
+       if (!buffer)
+               return NULL;
+
+       return buffer->data;
 }
 
 static void frame_done_cb(void* data, struct wl_callback* callback, uint32_t time);
@@ -654,7 +672,7 @@ static void frame_done_cb(void* data, struct wl_callback* callback, uint32_t tim
        UwacFrameDoneEvent* event;
 
        wl_callback_destroy(callback);
-       window->pendingBuffer = NULL;
+       window->pendingBufferIdx = -1;
        event = (UwacFrameDoneEvent*)UwacDisplayNewEvent(window->display, UWAC_EVENT_FRAME_DONE);
 
        if (event)
@@ -677,13 +695,20 @@ UwacReturnCode UwacWindowAddDamage(UwacWindow* window, uint32_t x, uint32_t y, u
                                    uint32_t height)
 {
        RECTANGLE_16 box;
+       UwacBuffer* buf;
 
        box.left = x;
        box.top = y;
        box.right = x + width;
        box.bottom = y + height;
 
-       UwacBuffer* buf = window->drawingBuffer;
+       if (window->drawingBufferIdx < 0)
+               return UWAC_ERROR_INTERNAL;
+
+       buf = &window->buffers[window->drawingBufferIdx];
+       if (!buf)
+               return UWAC_ERROR_INTERNAL;
+
        if (!region16_union_rect(&buf->damage, &buf->damage, &box))
                return UWAC_ERROR_INTERNAL;
 
@@ -695,7 +720,7 @@ UwacReturnCode UwacWindowAddDamage(UwacWindow* window, uint32_t x, uint32_t y, u
 UwacReturnCode UwacWindowGetDrawingBufferGeometry(UwacWindow* window, UwacSize* geometry,
                                                   size_t* stride)
 {
-       if (!window || !window->drawingBuffer)
+       if (!window || (window->drawingBufferIdx < 0))
                return UWAC_ERROR_INTERNAL;
 
        if (geometry)
@@ -712,20 +737,25 @@ UwacReturnCode UwacWindowGetDrawingBufferGeometry(UwacWindow* window, UwacSize*
 
 UwacReturnCode UwacWindowSubmitBuffer(UwacWindow* window, bool copyContentForNextFrame)
 {
-       UwacBuffer* drawingBuffer = window->drawingBuffer;
+       UwacBuffer* drawingBuffer;
+       UwacBuffer* nextBuffer;
+
+       if (window->drawingBufferIdx < 0)
+               return UWAC_ERROR_INTERNAL;
+
+       drawingBuffer = &window->buffers[window->drawingBufferIdx];
 
-       if (window->pendingBuffer || !drawingBuffer->dirty)
+       if ((window->pendingBufferIdx >= 0) || !drawingBuffer->dirty)
                return UWAC_SUCCESS;
 
-       window->pendingBuffer = drawingBuffer;
-       window->drawingBuffer = UwacWindowFindFreeBuffer(window);
+       window->pendingBufferIdx = window->drawingBufferIdx;
+       nextBuffer = UwacWindowFindFreeBuffer(window, &window->drawingBufferIdx);
 
-       if (!window->drawingBuffer)
+       if ((!nextBuffer) || (window->drawingBufferIdx < 0))
                return UWAC_ERROR_NOMEMORY;
 
        if (copyContentForNextFrame)
-               memcpy(window->drawingBuffer->data, window->pendingBuffer->data,
-                      window->stride * window->height);
+               memcpy(nextBuffer->data, drawingBuffer->data, window->stride * window->height);
 
        UwacSubmitBufferPtr(window, drawingBuffer);
        return UWAC_SUCCESS;