From 091b1554da0c64afe481f89d5f049fed8587ad53 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Tue, 25 May 2021 11:39:01 +0300 Subject: [PATCH] shared/cairo-util: fix leak from load_cairo_surface() Fixes ASan reported leaks: Direct leak of 256 byte(s) in 1 object(s) allocated from: #0 0x7f8266f2d330 in __interceptor_malloc (/lib/x86_64-linux-gnu/libasan.so.5+0xe9330) #1 0x7f8266c8589a (/lib/x86_64-linux-gnu/libpixman-1.so.0+0x5089a) #2 0x7f8266c4ea77 (/lib/x86_64-linux-gnu/libpixman-1.so.0+0x19a77) #3 0x55fa7818f8e8 in load_png ../../git/weston/shared/image-loader.c:297 #4 0x55fa7819039e in load_image ../../git/weston/shared/image-loader.c:423 #5 0x55fa78187b3e in load_cairo_surface ../../git/weston/shared/cairo-util.c:354 #6 0x55fa7815ff8a in background_draw ../../git/weston/clients/desktop-shell.c:779 #7 0x55fa7817b2c2 in widget_redraw ../../git/weston/clients/window.c:4520 #8 0x55fa7817b831 in surface_redraw ../../git/weston/clients/window.c:4578 #9 0x55fa7817b9a7 in idle_redraw ../../git/weston/clients/window.c:4607 #10 0x55fa78184ea4 in display_run ../../git/weston/clients/window.c:6527 #11 0x55fa781646fb in main ../../git/weston/clients/desktop-shell.c:1556 #12 0x7f826659709a in __libc_start_main ../csu/libc-start.c:308 #13 0x55fa7815c0a9 in _start (/home/pq/build/weston-meson/clients/weston-desktop-shell+0x120a9) Indirect leak of 8024 byte(s) in 1 object(s) allocated from: #0 0x7f8266f2d330 in __interceptor_malloc (/lib/x86_64-linux-gnu/libasan.so.5+0xe9330) #1 0x55fa7818f5e7 in load_png ../../git/weston/shared/image-loader.c:275 #2 0x55fa7819039e in load_image ../../git/weston/shared/image-loader.c:423 #3 0x55fa78187b3e in load_cairo_surface ../../git/weston/shared/cairo-util.c:354 #4 0x55fa7815ff8a in background_draw ../../git/weston/clients/desktop-shell.c:779 #5 0x55fa7817b2c2 in widget_redraw ../../git/weston/clients/window.c:4520 #6 0x55fa7817b831 in surface_redraw ../../git/weston/clients/window.c:4578 #7 0x55fa7817b9a7 in idle_redraw ../../git/weston/clients/window.c:4607 #8 0x55fa78184ea4 in display_run ../../git/weston/clients/window.c:6527 #9 0x55fa781646fb in main ../../git/weston/clients/desktop-shell.c:1556 #10 0x7f826659709a in __libc_start_main ../csu/libc-start.c:308 #11 0x55fa7815c0a9 in _start (/home/pq/build/weston-meson/clients/weston-desktop-shell+0x120a9) from the command ASAN_OPTIONS=fast_unwind_on_malloc=0,malloc_context_size=50 \ LSAN_OPTIONS=suppressions=/home/pq/git/weston/.gitlab-ci/leak-sanitizer.supp \ ./tests/test-viewporter test_viewporter_bad_source_rect by recording the pixman image as user data so it can be freed when the surface is destroyed. Signed-off-by: Pekka Paalanen --- shared/cairo-util.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/shared/cairo-util.c b/shared/cairo-util.c index f558e1d0..3a32b90a 100644 --- a/shared/cairo-util.c +++ b/shared/cairo-util.c @@ -344,9 +344,21 @@ rounded_rect(cairo_t *cr, int x0, int y0, int x1, int y1, int radius) cairo_close_path(cr); } +static void +loaded_cairo_surface_destructor(void *data) +{ + pixman_image_t *image = data; + + pixman_image_unref(image); +} + +static const cairo_user_data_key_t weston_cairo_util_load_cairo_surface_key; + cairo_surface_t * load_cairo_surface(const char *filename) { + cairo_surface_t *surface; + cairo_status_t ret; pixman_image_t *image; int width, height, stride; void *data; @@ -361,8 +373,25 @@ load_cairo_surface(const char *filename) height = pixman_image_get_height(image); stride = pixman_image_get_stride(image); - return cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, - width, height, stride); + surface = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, + width, height, stride); + ret = cairo_surface_status(surface); + if (ret != CAIRO_STATUS_SUCCESS) + goto fail; + + ret = cairo_surface_set_user_data(surface, + &weston_cairo_util_load_cairo_surface_key, + image, + loaded_cairo_surface_destructor); + if (ret != CAIRO_STATUS_SUCCESS) + goto fail; + + return surface; + +fail: + cairo_surface_destroy(surface); + pixman_image_unref(image); + return NULL; } void