From 87e7ba884c4f27a587868ea42170b25a7a5d0fa9 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Sun, 22 Jan 2023 02:03:02 +0200 Subject: [PATCH 26/26] gtk: Fix memory leak on failing sprite loading See osdn #46584 Signed-off-by: Marko Lindqvist --- client/gui-gtk-3.0/sprite.c | 25 +++++++++++++++++-------- client/gui-gtk-3.22/sprite.c | 25 +++++++++++++++++-------- client/gui-gtk-4.0/sprite.c | 25 +++++++++++++++++-------- 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/client/gui-gtk-3.0/sprite.c b/client/gui-gtk-3.0/sprite.c index f8e7a873be..7dd1912608 100644 --- a/client/gui-gtk-3.0/sprite.c +++ b/client/gui-gtk-3.0/sprite.c @@ -163,9 +163,9 @@ static void surf_destroy_callback(void *data) } /************************************************************************//** - Load the given graphics file into a sprite. This function loads an + Load the given graphics file into a sprite. This function loads an entire image file, which may later be broken up into individual sprites - with crop_sprite. + with crop_sprite(). ****************************************************************************/ struct sprite *load_gfxfile(const char *filename) { @@ -189,6 +189,8 @@ struct sprite *load_gfxfile(const char *filename) } spr = fc_malloc(sizeof(*spr)); + spr->surface = NULL; + width = gdk_pixbuf_get_width(pb); height = gdk_pixbuf_get_height(pb); pbdata = gdk_pixbuf_get_pixels(pb); @@ -199,7 +201,8 @@ struct sprite *load_gfxfile(const char *filename) cairo_stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); if (cairo_stride <= 0) { log_error("Cairo does not give stride for width %d", width); - free(spr); + free_sprite(spr); + return NULL; } @@ -221,8 +224,10 @@ struct sprite *load_gfxfile(const char *filename) data[j * 4 + 0] = tmp; } else { tmp = MULTI_UNc(pbdata[j * channels + 2], pbdata[j * channels + 3]); - data[j * 4 + 1] = MULTI_UNc(pbdata[j * channels + 1], pbdata[j * channels + 3]); - data[j * 4 + 2] = MULTI_UNc(pbdata[j * channels + 0], pbdata[j * channels + 3]); + data[j * 4 + 1] = MULTI_UNc(pbdata[j * channels + 1], + pbdata[j * channels + 3]); + data[j * 4 + 2] = MULTI_UNc(pbdata[j * channels + 0], + pbdata[j * channels + 3]); data[j * 4 + 0] = tmp; data[j * 4 + 3] = pbdata[j * channels + 3]; } @@ -245,9 +250,10 @@ struct sprite *load_gfxfile(const char *filename) spr->surface = cairo_image_surface_create_for_data(cairo_data, CAIRO_FORMAT_ARGB32, width, height, cairo_stride); - if (spr->surface == NULL || cairo_surface_status(spr->surface) != CAIRO_STATUS_SUCCESS) { + if (spr->surface == NULL + || cairo_surface_status(spr->surface) != CAIRO_STATUS_SUCCESS) { log_error("Cairo image surface creation error"); - free(spr); + free_sprite(spr); free(cairo_data); return NULL; @@ -271,7 +277,10 @@ struct sprite *load_gfxfile(const char *filename) ****************************************************************************/ void free_sprite(struct sprite * s) { - cairo_surface_destroy(s->surface); + if (s->surface != NULL) { + cairo_surface_destroy(s->surface); + } + free(s); } diff --git a/client/gui-gtk-3.22/sprite.c b/client/gui-gtk-3.22/sprite.c index 83d0677f3a..2cf4883661 100644 --- a/client/gui-gtk-3.22/sprite.c +++ b/client/gui-gtk-3.22/sprite.c @@ -163,9 +163,9 @@ static void surf_destroy_callback(void *data) } /************************************************************************//** - Load the given graphics file into a sprite. This function loads an + Load the given graphics file into a sprite. This function loads an entire image file, which may later be broken up into individual sprites - with crop_sprite. + with crop_sprite(). ****************************************************************************/ struct sprite *load_gfxfile(const char *filename) { @@ -189,6 +189,8 @@ struct sprite *load_gfxfile(const char *filename) } spr = fc_malloc(sizeof(*spr)); + spr->surface = NULL; + width = gdk_pixbuf_get_width(pb); height = gdk_pixbuf_get_height(pb); pbdata = gdk_pixbuf_get_pixels(pb); @@ -199,7 +201,8 @@ struct sprite *load_gfxfile(const char *filename) cairo_stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); if (cairo_stride <= 0) { log_error("Cairo does not give stride for width %d", width); - free(spr); + free_sprite(spr); + return NULL; } @@ -221,8 +224,10 @@ struct sprite *load_gfxfile(const char *filename) data[j * 4 + 0] = tmp; } else { tmp = MULTI_UNc(pbdata[j * channels + 2], pbdata[j * channels + 3]); - data[j * 4 + 1] = MULTI_UNc(pbdata[j * channels + 1], pbdata[j * channels + 3]); - data[j * 4 + 2] = MULTI_UNc(pbdata[j * channels + 0], pbdata[j * channels + 3]); + data[j * 4 + 1] = MULTI_UNc(pbdata[j * channels + 1], + pbdata[j * channels + 3]); + data[j * 4 + 2] = MULTI_UNc(pbdata[j * channels + 0], + pbdata[j * channels + 3]); data[j * 4 + 0] = tmp; data[j * 4 + 3] = pbdata[j * channels + 3]; } @@ -245,9 +250,10 @@ struct sprite *load_gfxfile(const char *filename) spr->surface = cairo_image_surface_create_for_data(cairo_data, CAIRO_FORMAT_ARGB32, width, height, cairo_stride); - if (spr->surface == NULL || cairo_surface_status(spr->surface) != CAIRO_STATUS_SUCCESS) { + if (spr->surface == NULL + || cairo_surface_status(spr->surface) != CAIRO_STATUS_SUCCESS) { log_error("Cairo image surface creation error"); - free(spr); + free_sprite(spr); free(cairo_data); return NULL; @@ -271,7 +277,10 @@ struct sprite *load_gfxfile(const char *filename) ****************************************************************************/ void free_sprite(struct sprite * s) { - cairo_surface_destroy(s->surface); + if (s->surface != NULL) { + cairo_surface_destroy(s->surface); + } + free(s); } diff --git a/client/gui-gtk-4.0/sprite.c b/client/gui-gtk-4.0/sprite.c index 18d5641594..2beffadbb1 100644 --- a/client/gui-gtk-4.0/sprite.c +++ b/client/gui-gtk-4.0/sprite.c @@ -163,9 +163,9 @@ static void surf_destroy_callback(void *data) } /************************************************************************//** - Load the given graphics file into a sprite. This function loads an + Load the given graphics file into a sprite. This function loads an entire image file, which may later be broken up into individual sprites - with crop_sprite. + with crop_sprite(). ****************************************************************************/ struct sprite *load_gfxfile(const char *filename) { @@ -189,6 +189,8 @@ struct sprite *load_gfxfile(const char *filename) } spr = fc_malloc(sizeof(*spr)); + spr->surface = NULL; + width = gdk_pixbuf_get_width(pb); height = gdk_pixbuf_get_height(pb); pbdata = gdk_pixbuf_get_pixels(pb); @@ -199,7 +201,8 @@ struct sprite *load_gfxfile(const char *filename) cairo_stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); if (cairo_stride <= 0) { log_error("Cairo does not give stride for width %d", width); - free(spr); + free_sprite(spr); + return NULL; } @@ -221,8 +224,10 @@ struct sprite *load_gfxfile(const char *filename) data[j * 4 + 0] = tmp; } else { tmp = MULTI_UNc(pbdata[j * channels + 2], pbdata[j * channels + 3]); - data[j * 4 + 1] = MULTI_UNc(pbdata[j * channels + 1], pbdata[j * channels + 3]); - data[j * 4 + 2] = MULTI_UNc(pbdata[j * channels + 0], pbdata[j * channels + 3]); + data[j * 4 + 1] = MULTI_UNc(pbdata[j * channels + 1], + pbdata[j * channels + 3]); + data[j * 4 + 2] = MULTI_UNc(pbdata[j * channels + 0], + pbdata[j * channels + 3]); data[j * 4 + 0] = tmp; data[j * 4 + 3] = pbdata[j * channels + 3]; } @@ -245,9 +250,10 @@ struct sprite *load_gfxfile(const char *filename) spr->surface = cairo_image_surface_create_for_data(cairo_data, CAIRO_FORMAT_ARGB32, width, height, cairo_stride); - if (spr->surface == NULL || cairo_surface_status(spr->surface) != CAIRO_STATUS_SUCCESS) { + if (spr->surface == NULL + || cairo_surface_status(spr->surface) != CAIRO_STATUS_SUCCESS) { log_error("Cairo image surface creation error"); - free(spr); + free_sprite(spr); free(cairo_data); return NULL; @@ -271,7 +277,10 @@ struct sprite *load_gfxfile(const char *filename) ****************************************************************************/ void free_sprite(struct sprite * s) { - cairo_surface_destroy(s->surface); + if (s->surface != NULL) { + cairo_surface_destroy(s->surface); + } + free(s); } -- 2.39.0