From 87d0bc50d53dc216efb2b04495f090616318bc5c Mon Sep 17 00:00:00 2001 From: Berke Güzel Date: Tue, 13 Oct 2026 13:18:53 +0300 Subject: test(app): destroy a surface from its input event callback The test pushes two key events into a Wayland surface's queue. The first event's callback destroys the surface. The run must end cleanly, without delivering the second event. Before 71091ca, ASan reported a heap-use-after-free in app_runner_dispatch_input_events. The test skips when WAYLAND_DISPLAY is unset. Co-Authored-By: Claude Opus 5.5 --- tests/meson.build | 4 +++ tests/wayland/test_app_input.c | 60 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 tests/wayland/test_app_input.c (limited to 'tests') diff --git a/tests/meson.build b/tests/meson.build index f74e3f8..c06fcca 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -157,6 +157,10 @@ if has_wayland dependencies: yasl_dep, ) test('ime-ownership', ime_test) + app_input_test = executable('yasl-app-input-test', 'wayland/test_app_input.c', + include_directories: inc, dependencies: yasl_dep, + ) + test('app-input-destroy', app_input_test) tablet_wayland_test = executable('yasl-tablet-wayland-test', 'wayland/test_tablet.c', include_directories: inc, dependencies: yasl_dep, ) diff --git a/tests/wayland/test_app_input.c b/tests/wayland/test_app_input.c new file mode 100644 index 0000000..24b8b64 --- /dev/null +++ b/tests/wayland/test_app_input.c @@ -0,0 +1,60 @@ +/* An input event callback that destroys its own surface. The app runner + * must not touch the surface's entry after the callback, and must not + * deliver the surface's remaining input. Needs a Wayland compositor. */ +#include "wayland/internal.h" +#include "yasl/app.h" + +#include +#include + +struct test_state { + int keys; +}; + +static void push_key(struct yasl_surface *s) +{ + struct yasl_input_event ev = { + .surface = s, + .kind = YASL_INPUT_KEY, + .key = { .key = YASL_KEY_A, .action = YASL_KEY_PRESS }, + }; + assert(input_queue_push(&((struct wayland_surface *)s)->input, &ev)); +} + +static int on_init(void *ud, struct yasl_display *d) +{ + (void)ud; + struct yasl_surface *s = yasl_surface_create_toplevel(d, + &(struct yasl_surface_spec){ .title = "App Input Test", .size = {64, 64} }); + assert(s); + push_key(s); + push_key(s); + return YASL_APP_CONTINUE; +} + +static int on_event(void *ud, const struct yasl_event *ev) +{ + struct test_state *state = ud; + if (ev->type == YASL_EVENT_KEY) { + state->keys++; + yasl_surface_destroy(ev->surface); + } + return YASL_APP_CONTINUE; +} + +int main(void) +{ + if (!getenv("WAYLAND_DISPLAY")) + return 77; + struct test_state state = {0}; + int res = yasl_run(&(struct yasl_app_desc){ + .app_id = "org.yasl.test.app-input", + .backend = YASL_BACKEND_WAYLAND, + .userdata = &state, + .init = on_init, + .event = on_event, + }); + assert(res == 0); + assert(state.keys == 1); + return 0; +} -- cgit v1.2.3