From 3b3e81f42e0bf05e606f40ac0145977766283548 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 29 Nov 2013 17:47:09 +0200 Subject: cursor: handle running out of buffer space If posix_fallocate is available, use it to detect when we are running out of buffer space. Propagate the failure properly through the various functions, stopping loading cursors but keeping the cursors that were already successfully loaded. This may result in an animated cursor not having all of its images, or a cursor theme not having all of its cursors. When that happens, the failure is NOT communicated to the application. Instead, the application will get NULL from wl_cursor_theme_get_cursor() for a cursor that was not loaded successfully. If an animated cursor is missing only some images, the animation is truncated but the cursor is still available. This patch relies on the commit "os: use posix_fallocate in creating sharable buffers" for defining HAVE_POSIX_FALLOCATE. Signed-off-by: Pekka Paalanen --- cursor/wayland-cursor.c | 67 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 16 deletions(-) (limited to 'cursor') diff --git a/cursor/wayland-cursor.c b/cursor/wayland-cursor.c index 25e51c2..3dadbdd 100644 --- a/cursor/wayland-cursor.c +++ b/cursor/wayland-cursor.c @@ -20,6 +20,7 @@ * OF THIS SOFTWARE. */ +#include "config.h" #include "xcursor.h" #include "wayland-cursor.h" #include "wayland-client.h" @@ -28,6 +29,8 @@ #include #include #include +#include +#include #include "os-compatibility.h" @@ -79,6 +82,12 @@ shm_pool_resize(struct shm_pool *pool, int size) if (ftruncate(pool->fd, size) < 0) return 0; +#ifdef HAVE_POSIX_FALLOCATE + errno = posix_fallocate(pool->fd, 0, size); + if (errno != 0) + return 0; +#endif + wl_shm_pool_resize(pool->pool, size); munmap(pool->data, pool->size); @@ -199,21 +208,15 @@ wl_cursor_create_from_data(struct cursor_metadata *metadata, cursor->cursor.image_count = 1; cursor->cursor.images = malloc(sizeof *cursor->cursor.images); - if (!cursor->cursor.images) { - free(cursor); - return NULL; - } + if (!cursor->cursor.images) + goto err_free_cursor; cursor->cursor.name = strdup(metadata->name); cursor->total_delay = 0; image = malloc(sizeof *image); - if (!image) { - free(cursor->cursor.name); - free(cursor->cursor.images); - free(cursor); - return NULL; - } + if (!image) + goto err_free_images; cursor->cursor.images[0] = (struct wl_cursor_image *) image; image->theme = theme; @@ -226,10 +229,25 @@ wl_cursor_create_from_data(struct cursor_metadata *metadata, size = metadata->width * metadata->height * sizeof(uint32_t); image->offset = shm_pool_allocate(theme->pool, size); + + if (image->offset < 0) + goto err_free_image; + memcpy(theme->pool->data + image->offset, cursor_data + metadata->offset, size); return &cursor->cursor; + +err_free_image: + free(image); + +err_free_images: + free(cursor->cursor.name); + free(cursor->cursor.images); + +err_free_cursor: + free(cursor); + return NULL; } static void @@ -240,12 +258,17 @@ load_default_theme(struct wl_cursor_theme *theme) free(theme->name); theme->name = strdup("default"); - theme->cursor_count = ARRAY_LENGTH(cursor_metadata);; + theme->cursor_count = ARRAY_LENGTH(cursor_metadata); theme->cursors = malloc(theme->cursor_count * sizeof(*theme->cursors)); - for (i = 0; i < theme->cursor_count; ++i) + for (i = 0; i < theme->cursor_count; ++i) { theme->cursors[i] = wl_cursor_create_from_data(&cursor_metadata[i], theme); + + if (theme->cursors[i] == NULL) + break; + } + theme->cursor_count = i; } static struct wl_cursor * @@ -260,7 +283,6 @@ wl_cursor_create_from_xcursor_images(XcursorImages *images, if (!cursor) return NULL; - cursor->cursor.image_count = images->nimage; cursor->cursor.images = malloc(images->nimage * sizeof cursor->cursor.images[0]); if (!cursor->cursor.images) { @@ -273,7 +295,6 @@ wl_cursor_create_from_xcursor_images(XcursorImages *images, for (i = 0; i < images->nimage; i++) { image = malloc(sizeof *image); - cursor->cursor.images[i] = (struct wl_cursor_image *) image; image->theme = theme; image->buffer = NULL; @@ -283,13 +304,27 @@ wl_cursor_create_from_xcursor_images(XcursorImages *images, image->image.hotspot_x = images->images[i]->xhot; image->image.hotspot_y = images->images[i]->yhot; image->image.delay = images->images[i]->delay; - cursor->total_delay += image->image.delay; - /* copy pixels to shm pool */ size = image->image.width * image->image.height * 4; image->offset = shm_pool_allocate(theme->pool, size); + if (image->offset < 0) { + free(image); + break; + } + + /* copy pixels to shm pool */ memcpy(theme->pool->data + image->offset, images->images[i]->pixels, size); + cursor->total_delay += image->image.delay; + cursor->cursor.images[i] = (struct wl_cursor_image *) image; + } + cursor->cursor.image_count = i; + + if (cursor->cursor.image_count == 0) { + free(cursor->cursor.name); + free(cursor->cursor.images); + free(cursor); + return NULL; } return &cursor->cursor; -- cgit v1.2.3