mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-03 21:40:40 +01:00
lua: ignore unsupported event codes in modified frames
If a plugin adds events to an event frame that are not supported by the target device we may eventually dereference a null pointer (for ABS_* events) or, possibly, use an OOB index access (for buttons or keys). Let's filter out any events that the device doesn't support immediately. Fixes #1202 Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1324>
This commit is contained in:
parent
3250686e70
commit
533d5f6ee1
2 changed files with 66 additions and 14 deletions
|
|
@ -221,7 +221,9 @@ lua_push_evdev_frame(lua_State *L, struct evdev_frame *frame)
|
|||
}
|
||||
|
||||
static void
|
||||
lua_pop_evdev_frame(struct libinput_lua_plugin *plugin, struct evdev_frame *frame_out)
|
||||
lua_pop_evdev_frame(struct libinput_lua_plugin *plugin,
|
||||
struct libevdev *libevdev,
|
||||
struct evdev_frame *frame_out)
|
||||
{
|
||||
lua_State *L = plugin->L;
|
||||
|
||||
|
|
@ -252,7 +254,7 @@ lua_pop_evdev_frame(struct libinput_lua_plugin *plugin, struct evdev_frame *fram
|
|||
}
|
||||
|
||||
lua_getfield(L, -1, "usage");
|
||||
uint32_t usage = luaL_checkinteger(L, -1);
|
||||
uint32_t usage_value = luaL_checkinteger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, -1, "value");
|
||||
|
|
@ -261,13 +263,18 @@ lua_pop_evdev_frame(struct libinput_lua_plugin *plugin, struct evdev_frame *fram
|
|||
|
||||
lua_pop(L, 1); /* pop { usage = ..., value = ...} */
|
||||
|
||||
struct evdev_event *e = &events[nevents++];
|
||||
e->usage = evdev_usage_from_uint32_t(usage);
|
||||
e->value = value;
|
||||
evdev_usage_t usage = evdev_usage_from_uint32_t(usage_value);
|
||||
unsigned int type = evdev_usage_type(usage);
|
||||
unsigned int code = evdev_usage_code(usage);
|
||||
if (libevdev_has_event_code(libevdev, type, code)) {
|
||||
struct evdev_event *e = &events[nevents++];
|
||||
e->usage = usage;
|
||||
e->value = value;
|
||||
|
||||
if (evdev_usage_eq(e->usage, EVDEV_SYN_REPORT)) {
|
||||
lua_pop(L, 1); /* force-pop the nil */
|
||||
break;
|
||||
if (evdev_usage_eq(e->usage, EVDEV_SYN_REPORT)) {
|
||||
lua_pop(L, 1); /* force-pop the nil */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -417,7 +424,7 @@ libinput_lua_plugin_evdev_frame(struct libinput_plugin *libinput_plugin,
|
|||
|
||||
if (!libinput_lua_pcall(plugin, 3, 1))
|
||||
return;
|
||||
lua_pop_evdev_frame(plugin, frame);
|
||||
lua_pop_evdev_frame(plugin, evdev->evdev, frame);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -932,10 +939,10 @@ evdevdevice_disconnect(lua_State *L)
|
|||
}
|
||||
|
||||
static struct evdev_frame *
|
||||
evdevdevice_frame(lua_State *L, struct libinput_lua_plugin *plugin)
|
||||
evdevdevice_frame(lua_State *L, struct libinput_lua_plugin *plugin, EvdevDevice *device)
|
||||
{
|
||||
auto frame = evdev_frame_new(64);
|
||||
lua_pop_evdev_frame(plugin, frame);
|
||||
lua_pop_evdev_frame(plugin, device->evdev, frame);
|
||||
|
||||
struct libinput *libinput = lua_get_libinput(L);
|
||||
uint64_t now = libinput_now(libinput);
|
||||
|
|
@ -961,7 +968,7 @@ evdevdevice_inject_frame(lua_State *L)
|
|||
if (!plugin->in_timer_func) {
|
||||
return luaL_error(L, "Injecting events only possible in a timer func");
|
||||
}
|
||||
_unref_(evdev_frame) *frame = evdevdevice_frame(L, plugin);
|
||||
_unref_(evdev_frame) *frame = evdevdevice_frame(L, plugin, device);
|
||||
|
||||
/* Lua is unhappy if we inject an event which calls into our lua state
|
||||
* immediately so we need to queue this for later when we're out of the timer
|
||||
|
|
@ -988,7 +995,7 @@ evdevdevice_prepend_frame(lua_State *L)
|
|||
return 0;
|
||||
|
||||
struct libinput_lua_plugin *plugin = lua_get_libinput_lua_plugin(L);
|
||||
_unref_(evdev_frame) *frame = evdevdevice_frame(L, plugin);
|
||||
_unref_(evdev_frame) *frame = evdevdevice_frame(L, plugin, device);
|
||||
/* FIXME: need to really ensure that the device can never be dangling */
|
||||
libinput_plugin_prepend_evdev_frame(plugin->parent, device->device, frame);
|
||||
|
||||
|
|
@ -1009,7 +1016,7 @@ evdevdevice_append_frame(lua_State *L)
|
|||
return 0;
|
||||
|
||||
struct libinput_lua_plugin *plugin = lua_get_libinput_lua_plugin(L);
|
||||
_unref_(evdev_frame) *frame = evdevdevice_frame(L, plugin);
|
||||
_unref_(evdev_frame) *frame = evdevdevice_frame(L, plugin, device);
|
||||
|
||||
/* FIXME: need to really ensure that the device can never be dangling */
|
||||
libinput_plugin_append_evdev_frame(plugin->parent, device->device, frame);
|
||||
|
|
|
|||
|
|
@ -868,6 +868,50 @@ START_TEST(lua_append_prepend_frame)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(lua_ignore_unsupported_codes)
|
||||
{
|
||||
_destroy_(tmpdir) *tmpdir = tmpdir_create(NULL);
|
||||
_autofree_ char *lua = strdup_printf(
|
||||
"libinput:register({1})\n"
|
||||
"function frame_handler(device, frame, timestamp)\n"
|
||||
" local events = {}\n"
|
||||
" for _, v in ipairs(frame) do\n"
|
||||
" table.insert(events, { usage = v.usage, value = v.value })\n"
|
||||
" end\n"
|
||||
" table.insert(events, { usage = evdev.ABS_X, value = 1000 })\n"
|
||||
" table.insert(events, { usage = evdev.ABS_Y, value = 100 })\n"
|
||||
" table.insert(events, { usage = evdev.BTN_BACK, value = 1 })\n"
|
||||
" table.insert(events, { usage = evdev.BTN_LEFT, value = 1 })\n" /* this
|
||||
one actually exists */
|
||||
" return events\n"
|
||||
"end\n"
|
||||
"libinput:connect(\"new-evdev-device\", function(device)\n"
|
||||
" device:connect(\"evdev-frame\", frame_handler)\n"
|
||||
"end)\n");
|
||||
_autofree_ char *path = litest_write_plugin(tmpdir->path, lua);
|
||||
_litest_context_destroy_ struct libinput *li =
|
||||
litest_create_context_with_plugindir(tmpdir->path);
|
||||
libinput_plugin_system_load_plugins(li, LIBINPUT_PLUGIN_FLAG_NONE);
|
||||
litest_drain_events(li);
|
||||
|
||||
_destroy_(litest_device) *device = litest_add_device(li, LITEST_MOUSE);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_event(device, EV_REL, REL_X, 1);
|
||||
litest_event(device, EV_REL, REL_Y, 2);
|
||||
litest_event(device, EV_SYN, SYN_REPORT, 0);
|
||||
litest_dispatch(li);
|
||||
litest_timeout_debounce(li);
|
||||
litest_dispatch(li);
|
||||
|
||||
_destroy_(libinput_event) *ev = libinput_get_event(li);
|
||||
litest_is_motion_event(ev);
|
||||
litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(lua_inject_frame)
|
||||
{
|
||||
bool in_timer = litest_test_param_get_bool(test_env->params, "in_timer");
|
||||
|
|
@ -1191,6 +1235,7 @@ TEST_COLLECTION(lua)
|
|||
litest_add_no_device(lua_device_info);
|
||||
litest_add_no_device(lua_set_absinfo);
|
||||
litest_add_no_device(lua_enable_disable_evdev_usage);
|
||||
litest_add_no_device(lua_ignore_unsupported_codes);
|
||||
|
||||
litest_with_parameters(params,
|
||||
"which", 'I', 3,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue