From f1e46894cb7f705550d1dcb56e882a7ccdf44c47 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 16 Jun 2020 13:54:12 +0200 Subject: [PATCH] Fixed double free for uwac buffers (cherry picked from commit 1bc48b058f013a8c88db2a1d7da2ad25dcd3bc4c) --- uwac/libuwac/uwac-priv.h | 3 +- uwac/libuwac/uwac-window.c | 82 +++++++++++++++++++++++++++++++--------------- 2 files changed, 58 insertions(+), 27 deletions(-) diff --git a/uwac/libuwac/uwac-priv.h b/uwac/libuwac/uwac-priv.h index 75ad6e0..2ef073d 100644 --- a/uwac/libuwac/uwac-priv.h +++ b/uwac/libuwac/uwac-priv.h @@ -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; diff --git a/uwac/libuwac/uwac-window.c b/uwac/libuwac/uwac-window.c index f76d43b..2f424e8 100644 --- a/uwac/libuwac/uwac-window.c +++ b/uwac/libuwac/uwac-window.c @@ -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; -- 2.7.4