[PATCH 1/2] wayland-cursor: Introduce size_t, improve error handling

Martin Minarik minarik11 at student.fiit.stuba.sk
Fri Feb 1 08:44:33 PST 2013


The size_t is introduced, accomodating for the possibility of
a large addres space.
The error handling is improved, in particular the memory leaks
are fixed.
---
 cursor/wayland-cursor.c |   88 +++++++++++++++++++++++++++++++++--------------
 1 file changed, 63 insertions(+), 25 deletions(-)

diff --git a/cursor/wayland-cursor.c b/cursor/wayland-cursor.c
index 25e51c2..821ef31 100644
--- a/cursor/wayland-cursor.c
+++ b/cursor/wayland-cursor.c
@@ -36,13 +36,13 @@
 struct shm_pool {
 	struct wl_shm_pool *pool;
 	int fd;
-	unsigned int size;
-	unsigned int used;
+	size_t size;
+	size_t used;
 	char *data;
 };
 
 static struct shm_pool *
-shm_pool_create(struct wl_shm *shm, int size)
+shm_pool_create(struct wl_shm *shm, size_t size)
 {
 	struct shm_pool *pool;
 
@@ -74,35 +74,53 @@ err_free:
 }
 
 static int
-shm_pool_resize(struct shm_pool *pool, int size)
+shm_pool_resize(struct shm_pool *pool, size_t size)
 {
 	if (ftruncate(pool->fd, size) < 0)
-		return 0;
+		goto err_unmap;
 
 	wl_shm_pool_resize(pool->pool, size);
 
-	munmap(pool->data, pool->size);
+	if (-1 == munmap(pool->data, pool->size)) {
+		goto err;
+	}
 
 	pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
 			  pool->fd, 0);
+
+	if (pool->data == MAP_FAILED) {
+		goto err;
+	}
 	pool->size = size;
 
 	return 1;
+err_unmap:
+	munmap(pool->data, pool->size);
+err:
+	wl_shm_pool_destroy(pool->pool);
+	pool->pool = NULL;
+	close(pool->fd);
+	free(pool);
+	return 0;
 }
 
 static int
-shm_pool_allocate(struct shm_pool *pool, int size)
+shm_pool_allocate(struct shm_pool *pool, size_t size, size_t *offset)
 {
-	int offset;
+	const size_t need = pool->used + size;
+
+	if (need > pool->size) {
+		const size_t double_s = 2 * pool->size;
+		const size_t new_size = double_s > need ? double_s : need;
 
-	if (pool->used + size > pool->size)
-		if (!shm_pool_resize(pool, 2 * pool->size + size))
+		if (!shm_pool_resize(pool, new_size))
 			return -1;
+	}
 
-	offset = pool->used;
+	*offset = pool->used;
 	pool->used += size;
 
-	return offset;
+	return 0;
 }
 
 static void
@@ -128,7 +146,7 @@ struct cursor_image {
 	struct wl_cursor_image image;
 	struct wl_cursor_theme *theme;
 	struct wl_buffer *buffer;
-	int offset; /* data offset of this image in the shm pool */
+	size_t offset; /* data offset of this image in the shm pool */
 };
 
 struct cursor {
@@ -200,8 +218,7 @@ 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;
+		goto err_cursor;
 	}
 
 	cursor->cursor.name = strdup(metadata->name);
@@ -209,10 +226,7 @@ wl_cursor_create_from_data(struct cursor_metadata *metadata,
 
 	image = malloc(sizeof *image);
 	if (!image) {
-		free(cursor->cursor.name);
-		free(cursor->cursor.images);
-		free(cursor);
-		return NULL;
+		goto err;
 	}
 
 	cursor->cursor.images[0] = (struct wl_cursor_image *) image;
@@ -225,11 +239,20 @@ wl_cursor_create_from_data(struct cursor_metadata *metadata,
 	image->image.delay = 0;
 
 	size = metadata->width * metadata->height * sizeof(uint32_t);
-	image->offset = shm_pool_allocate(theme->pool, size);
+	if (shm_pool_allocate(theme->pool, size, &image->offset)) {
+		goto err;
+	}
 	memcpy(theme->pool->data + image->offset,
 	       cursor_data + metadata->offset, size);
 
 	return &cursor->cursor;
+
+err:
+	free(cursor->cursor.name);
+	free(cursor->cursor.images);
+err_cursor:
+	free(cursor);
+	return NULL;
 }
 
 static void
@@ -264,8 +287,7 @@ wl_cursor_create_from_xcursor_images(XcursorImages *images,
 	cursor->cursor.images =
 		malloc(images->nimage * sizeof cursor->cursor.images[0]);
 	if (!cursor->cursor.images) {
-		free(cursor);
-		return NULL;
+		goto err;
 	}
 
 	cursor->cursor.name = strdup(images->name);
@@ -287,12 +309,28 @@ wl_cursor_create_from_xcursor_images(XcursorImages *images,
 
 		/* copy pixels to shm pool */
 		size = image->image.width * image->image.height * 4;
-		image->offset = shm_pool_allocate(theme->pool, size);
-		memcpy(theme->pool->data + image->offset,
-		       images->images[i]->pixels, size);
+		int fail = shm_pool_allocate(theme->pool, size, &image->offset);
+
+		if (fail == 0) {
+			memcpy(theme->pool->data + image->offset,
+			       images->images[i]->pixels, size);
+
+		}
+		if (fail == -1) {
+			/* on error, rollback the allocations. */
+			int j;
+			for (j = 0; j <= i; j++){
+				free(cursor->cursor.images[j]);
+			}
+
+			goto err;
+		}
 	}
 
 	return &cursor->cursor;
+err:
+	free(cursor);
+	return NULL;
 }
 
 static void
-- 
1.7.10.4



More information about the wayland-devel mailing list