From 21bd03f6d1b41134a484409a45a772d788054a04 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Thu, 13 Jun 2024 13:46:33 -0500 Subject: [PATCH] libweston: Return NULL from creation of animations that have finished Since the animation creation process kicks off the first frame of an animation, it's possible for the animation to be completed and destroyed before the pointer is returned. Some code in desktop shell stores these pointers to cancel an animation before starting a new similar one - but in some cases that leads to storing a pointer after the callback that should clear that pointer, setting up a later use after free. Instead, if the animation is finished and destroyed before the creation function exits, just return a NULL. Signed-off-by: Derek Foreman --- libweston/animation.c | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/libweston/animation.c b/libweston/animation.c index 17aeb353..8da9358c 100644 --- a/libweston/animation.c +++ b/libweston/animation.c @@ -167,10 +167,10 @@ handle_animation_view_destroy(struct wl_listener *listener, void *data) weston_view_animation_destroy(animation); } -static void -weston_view_animation_frame(struct weston_animation *base, - struct weston_output *output, - const struct timespec *time) +static bool +weston_view_animation_frame_internal(struct weston_animation *base, + struct weston_output *output, + const struct timespec *time) { struct weston_view_animation *animation = container_of(base, @@ -188,7 +188,7 @@ weston_view_animation_frame(struct weston_animation *base, wl_event_source_remove(animation->idle_destroy_source); weston_view_animation_destroy(animation); - return; + return true; } if (animation->frame) @@ -207,6 +207,16 @@ weston_view_animation_frame(struct weston_animation *base, */ if (animation->view->output_mask == 0) weston_compositor_schedule_repaint(compositor); + + return false; +} + +static void +weston_view_animation_frame(struct weston_animation *base, + struct weston_output *output, + const struct timespec *time) +{ + weston_view_animation_frame_internal(base, output, time); } static void @@ -265,13 +275,13 @@ weston_view_animation_create(struct weston_view *view, return animation; } -static void +static bool __attribute__ ((warn_unused_result)) weston_view_animation_run(struct weston_view_animation *animation) { struct timespec zero_time = { 0 }; animation->animation.frame_counter = 0; - weston_view_animation_frame(&animation->animation, NULL, &zero_time); + return weston_view_animation_frame_internal(&animation->animation, NULL, &zero_time); } static void @@ -321,7 +331,8 @@ weston_zoom_run(struct weston_view *view, float start, float stop, zoom->spring.friction = 1400; zoom->spring.previous = start - (stop - start) * 0.03; - weston_view_animation_run(zoom); + if (weston_view_animation_run(zoom)) + return NULL; return zoom; } @@ -362,7 +373,8 @@ weston_fade_run(struct weston_view *view, weston_view_set_alpha(view, start); weston_view_update_transform(view); - weston_view_animation_run(fade); + if (weston_view_animation_run(fade)) + return NULL; return fade; } @@ -415,7 +427,8 @@ weston_stable_fade_run(struct weston_view *front_view, float start, weston_view_set_alpha(front_view, start); weston_view_set_alpha(back_view, end); - weston_view_animation_run(fade); + if (weston_view_animation_run(fade)) + return NULL; return fade; } @@ -448,7 +461,8 @@ weston_slide_run(struct weston_view *view, float start, float stop, animation->spring.friction = 600; animation->spring.clip = WESTON_SPRING_BOUNCE; - weston_view_animation_run(animation); + if (weston_view_animation_run(animation)) + return NULL; return animation; } @@ -523,7 +537,8 @@ weston_move_scale_run_internal(struct weston_view *view, int dx, int dy, weston_spring_init(&animation->spring, 400.0, 0.0, 1.0); animation->spring.friction = 1150; - weston_view_animation_run(animation); + if (weston_view_animation_run(animation)) + return NULL; return animation; }