From 91fa2ff3959ae10d8fc1f8fb8955608faa71c56a Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 5 Mar 2020 16:24:25 +0100 Subject: [PATCH] surface: check buffer size is compatible with scale This relies on [1]. [1]: https://gitlab.freedesktop.org/wayland/wayland/-/commit/8d5fadad47aad420b0d83fffc8ad573766a9c75e --- types/wlr_surface.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/types/wlr_surface.c b/types/wlr_surface.c index dd022489..e453ddf6 100644 --- a/types/wlr_surface.c +++ b/types/wlr_surface.c @@ -145,17 +145,22 @@ static void surface_set_input_region(struct wl_client *client, * rectangle) but before applying the viewport scaling (via the viewport's * destination rectangle). */ -static void surface_state_viewport_src_size(struct wlr_surface_state *state, +static bool surface_state_viewport_src_size(struct wlr_surface_state *state, int *out_width, int *out_height) { if (state->buffer_width == 0 && state->buffer_height == 0) { *out_width = *out_height = 0; - return; + return true; } if (state->viewport.has_src) { *out_width = state->viewport.src.width; *out_height = state->viewport.src.height; } else { + if (state->buffer_width % state->scale != 0 || + state->buffer_height % state->scale != 0) { + return false; + } + int width = state->buffer_width / state->scale; int height = state->buffer_height / state->scale; if ((state->transform & WL_OUTPUT_TRANSFORM_90) != 0) { @@ -166,9 +171,11 @@ static void surface_state_viewport_src_size(struct wlr_surface_state *state, *out_width = width; *out_height = height; } + + return true; } -static void surface_state_finalize(struct wlr_surface *surface, +static bool surface_state_finalize(struct wlr_surface *surface, struct wlr_surface_state *state) { if ((state->committed & WLR_SURFACE_STATE_BUFFER)) { if (state->buffer_resource != NULL) { @@ -187,8 +194,13 @@ static void surface_state_finalize(struct wlr_surface *surface, state->height = state->viewport.dst_height; } } else { - surface_state_viewport_src_size(state, - &state->width, &state->height); + if (!surface_state_viewport_src_size(state, + &state->width, &state->height)) { + wl_resource_post_error(surface->resource, + WL_SURFACE_ERROR_INVALID_SIZE, + "Buffer size not divisible by scale"); + return false; + } } pixman_region32_intersect_rect(&state->surface_damage, @@ -197,6 +209,8 @@ static void surface_state_finalize(struct wlr_surface *surface, pixman_region32_intersect_rect(&state->buffer_damage, &state->buffer_damage, 0, 0, state->buffer_width, state->buffer_height); + + return true; } static void surface_update_damage(pixman_region32_t *buffer_damage, @@ -388,7 +402,9 @@ static void surface_update_input_region(struct wlr_surface *surface) { } static void surface_commit_pending(struct wlr_surface *surface) { - surface_state_finalize(surface, &surface->pending); + if (!surface_state_finalize(surface, &surface->pending)) { + return; + } if (surface->role && surface->role->precommit) { surface->role->precommit(surface);