wayland: Validate surfaces and window data before sending touch events Ensure that incoming touch events originate from valid surfaces owned by SDL and have proper window data before forwarding them to the touch subsystem, or the window focus pointer that is sent with the event may not be a pointer to an SDL window.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index 68268cd..a940f97 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -78,8 +78,8 @@
struct SDL_WaylandTouchPoint
{
SDL_TouchID id;
- float x;
- float y;
+ wl_fixed_t x;
+ wl_fixed_t y;
struct wl_surface *surface;
struct SDL_WaylandTouchPoint *prev;
@@ -94,7 +94,7 @@ struct SDL_WaylandTouchPointList
static struct SDL_WaylandTouchPointList touch_points = { NULL, NULL };
-static void touch_add(SDL_TouchID id, float x, float y, struct wl_surface *surface)
+static void touch_add(SDL_TouchID id, wl_fixed_t x, wl_fixed_t y, struct wl_surface *surface)
{
struct SDL_WaylandTouchPoint *tp = SDL_malloc(sizeof(struct SDL_WaylandTouchPoint));
@@ -115,7 +115,7 @@ static void touch_add(SDL_TouchID id, float x, float y, struct wl_surface *surfa
tp->next = NULL;
}
-static void touch_update(SDL_TouchID id, float x, float y)
+static void touch_update(SDL_TouchID id, wl_fixed_t x, wl_fixed_t y, struct wl_surface **surface)
{
struct SDL_WaylandTouchPoint *tp = touch_points.head;
@@ -123,13 +123,14 @@ static void touch_update(SDL_TouchID id, float x, float y)
if (tp->id == id) {
tp->x = x;
tp->y = y;
+ *surface = tp->surface;
}
tp = tp->next;
}
}
-static void touch_del(SDL_TouchID id, float *x, float *y, struct wl_surface **surface)
+static void touch_del(SDL_TouchID id, wl_fixed_t *x, wl_fixed_t *y, struct wl_surface **surface)
{
struct SDL_WaylandTouchPoint *tp = touch_points.head;
@@ -162,21 +163,6 @@ static void touch_del(SDL_TouchID id, float *x, float *y, struct wl_surface **su
}
}
-static struct wl_surface *touch_surface(SDL_TouchID id)
-{
- struct SDL_WaylandTouchPoint *tp = touch_points.head;
-
- while (tp) {
- if (tp->id == id) {
- return tp->surface;
- }
-
- tp = tp->next;
- }
-
- return NULL;
-}
-
/* Returns SDL_TRUE if a key repeat event was due */
static SDL_bool keyboard_repeat_handle(SDL_WaylandKeyboardRepeat *repeat_info, uint32_t elapsed)
{
@@ -814,49 +800,77 @@ static const struct wl_pointer_listener pointer_listener = {
pointer_handle_axis_value120 /* Version 8 */
};
-static void touch_handler_down(void *data, struct wl_touch *touch, unsigned int serial,
- unsigned int timestamp, struct wl_surface *surface,
+static void touch_handler_down(void *data, struct wl_touch *touch, uint32_t serial,
+ uint32_t timestamp, struct wl_surface *surface,
int id, wl_fixed_t fx, wl_fixed_t fy)
{
- SDL_WindowData *window_data = (SDL_WindowData *)wl_surface_get_user_data(surface);
- const double dblx = wl_fixed_to_double(fx) * window_data->pointer_scale_x;
- const double dbly = wl_fixed_to_double(fy) * window_data->pointer_scale_y;
- const float x = dblx / window_data->sdlwindow->w;
- const float y = dbly / window_data->sdlwindow->h;
+ struct SDL_WaylandInput *input = (struct SDL_WaylandInput *)data;
+ SDL_WindowData *window_data;
- touch_add(id, x, y, surface);
+ /* Check that this surface belongs to one of the SDL windows */
+ if (!SDL_WAYLAND_own_surface(surface)) {
+ return;
+ }
- SDL_SendTouch((SDL_TouchID)(intptr_t)touch, (SDL_FingerID)id, window_data->sdlwindow, SDL_TRUE, x, y, 1.0f);
+ touch_add(id, fx, fy, surface);
+ window_data = (SDL_WindowData *)wl_surface_get_user_data(surface);
+
+ if (window_data) {
+ const double dblx = wl_fixed_to_double(fx) * window_data->pointer_scale_x;
+ const double dbly = wl_fixed_to_double(fy) * window_data->pointer_scale_y;
+ const float x = dblx / window_data->sdlwindow->w;
+ const float y = dbly / window_data->sdlwindow->h;
+
+ SDL_SendTouch((SDL_TouchID)(intptr_t)touch, (SDL_FingerID)id,
+ window_data->sdlwindow, SDL_TRUE, x, y, 1.0f);
+ }
}
-static void touch_handler_up(void *data, struct wl_touch *touch, unsigned int serial,
- unsigned int timestamp, int id)
+static void touch_handler_up(void *data, struct wl_touch *touch, uint32_t serial,
+ uint32_t timestamp, int id)
{
- float x = 0, y = 0;
+ struct SDL_WaylandInput *input = (struct SDL_WaylandInput *)data;
+ wl_fixed_t fx = 0, fy = 0;
struct wl_surface *surface = NULL;
- SDL_Window *window = NULL;
- touch_del(id, &x, &y, &surface);
+ touch_del(id, &fx, &fy, &surface);
if (surface) {
SDL_WindowData *window_data = (SDL_WindowData *)wl_surface_get_user_data(surface);
- window = window_data->sdlwindow;
- }
- SDL_SendTouch((SDL_TouchID)(intptr_t)touch, (SDL_FingerID)id, window, SDL_FALSE, x, y, 0.0f);
+ if (window_data) {
+ const double dblx = wl_fixed_to_double(fx) * window_data->pointer_scale_x;
+ const double dbly = wl_fixed_to_double(fy) * window_data->pointer_scale_y;
+ const float x = dblx / window_data->sdlwindow->w;
+ const float y = dbly / window_data->sdlwindow->h;
+
+ SDL_SendTouch((SDL_TouchID)(intptr_t)touch, (SDL_FingerID)id,
+ window_data->sdlwindow, SDL_FALSE, x, y, 1.0f);
+ }
+ }
}
-static void touch_handler_motion(void *data, struct wl_touch *touch, unsigned int timestamp,
+static void touch_handler_motion(void *data, struct wl_touch *touch, uint32_t timestamp,
int id, wl_fixed_t fx, wl_fixed_t fy)
{
- SDL_WindowData *window_data = (SDL_WindowData *)wl_surface_get_user_data(touch_surface(id));
- const double dblx = wl_fixed_to_double(fx) * window_data->pointer_scale_x;
- const double dbly = wl_fixed_to_double(fy) * window_data->pointer_scale_y;
- const float x = dblx / window_data->sdlwindow->w;
- const float y = dbly / window_data->sdlwindow->h;
+ struct SDL_WaylandInput *input = (struct SDL_WaylandInput *)data;
+ struct wl_surface *surface = NULL;
- touch_update(id, x, y);
- SDL_SendTouchMotion((SDL_TouchID)(intptr_t)touch, (SDL_FingerID)id, window_data->sdlwindow, x, y, 1.0f);
+ touch_update(id, fx, fy, &surface);
+
+ if (surface) {
+ SDL_WindowData *window_data = (SDL_WindowData *)wl_surface_get_user_data(surface);
+
+ if (window_data) {
+ const double dblx = wl_fixed_to_double(fx) * window_data->pointer_scale_x;
+ const double dbly = wl_fixed_to_double(fy) * window_data->pointer_scale_y;
+ const float x = dblx / window_data->sdlwindow->w;
+ const float y = dbly / window_data->sdlwindow->h;
+
+ SDL_SendTouchMotion((SDL_TouchID)(intptr_t)touch, (SDL_FingerID)id,
+ window_data->sdlwindow, x, y, 1.0f);
+ }
+ }
}
static void touch_handler_frame(void *data, struct wl_touch *touch)