lua: drop compatibility to 5.1 to allow for luajit

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1192>
This commit is contained in:
Peter Hutterer 2025-07-15 14:39:30 +10:00
parent 9e37bc0cfa
commit 2723cadaeb
6 changed files with 58 additions and 48 deletions

View file

@ -98,11 +98,11 @@ variables:
# See the documentation here: # # See the documentation here: #
# https://wayland.freedesktop.org/libinput/doc/latest/building.html # # https://wayland.freedesktop.org/libinput/doc/latest/building.html #
############################################################################### ###############################################################################
FEDORA_PACKAGES: 'git-core gcc gcc-c++ pkgconf-pkg-config meson check-devel libudev-devel libevdev-devel doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx_rtd_theme python3-pytest-xdist libwacom-devel cairo-devel gtk4-devel glib2-devel mtdev-devel diffutils wayland-protocols-devel black clang clang-tools-extra jq rpmdevtools valgrind systemd-udev qemu-img qemu-system-x86-core qemu-system-aarch64-core jq python3-click python3-rich virtme-ng lua-devel' FEDORA_PACKAGES: 'git-core gcc gcc-c++ pkgconf-pkg-config meson check-devel libudev-devel libevdev-devel doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx_rtd_theme python3-pytest-xdist libwacom-devel cairo-devel gtk4-devel glib2-devel mtdev-devel diffutils wayland-protocols-devel black clang clang-tools-extra jq rpmdevtools valgrind systemd-udev qemu-img qemu-system-x86-core qemu-system-aarch64-core jq python3-click python3-rich virtme-ng luajit-devel'
DEBIAN_PACKAGES: 'git gcc g++ pkg-config meson check libudev-dev libevdev-dev doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx-rtd-theme python3-pytest-xdist libwacom-dev libcairo2-dev libgtk-3-dev libglib2.0-dev libmtdev-dev curl lua5.4-dev' DEBIAN_PACKAGES: 'git gcc g++ pkg-config meson check libudev-dev libevdev-dev doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx-rtd-theme python3-pytest-xdist libwacom-dev libcairo2-dev libgtk-3-dev libglib2.0-dev libmtdev-dev curl libluajit-5.1-dev'
UBUNTU_PACKAGES: 'git gcc g++ pkg-config meson check libudev-dev libevdev-dev doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx-rtd-theme python3-pytest-xdist libwacom-dev libcairo2-dev libgtk-3-dev libglib2.0-dev libmtdev-dev lua5.4-dev' UBUNTU_PACKAGES: 'git gcc g++ pkg-config meson check libudev-dev libevdev-dev doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx-rtd-theme python3-pytest-xdist libwacom-dev libcairo2-dev libgtk-3-dev libglib2.0-dev libmtdev-dev libluajit-5.1-dev'
ARCH_PACKAGES: 'git gcc pkgconfig meson check libsystemd libevdev python-pytest-xdist libwacom gtk4 mtdev diffutils lua' ARCH_PACKAGES: 'git gcc pkgconfig meson check libsystemd libevdev python-pytest-xdist libwacom gtk4 mtdev diffutils luajit'
ALPINE_PACKAGES: 'git gcc build-base pkgconfig meson check-dev eudev-dev libevdev-dev libwacom-dev cairo-dev gtk4.0-dev mtdev-dev bash lua5.4-dev' ALPINE_PACKAGES: 'git gcc build-base pkgconfig meson check-dev eudev-dev libevdev-dev libwacom-dev cairo-dev gtk4.0-dev mtdev-dev bash luajit-dev'
FREEBSD_PACKAGES: 'git pkgconf meson libepoll-shim libudev-devd libevdev libwacom gtk3 libmtdev bash wayland' FREEBSD_PACKAGES: 'git pkgconf meson libepoll-shim libudev-devd libevdev libwacom gtk3 libmtdev bash wayland'
############################ end of package lists ############################# ############################ end of package lists #############################
@ -110,12 +110,12 @@ variables:
# changing these will force rebuilding the associated image # changing these will force rebuilding the associated image
# Note: these tags have no meaning and are not tied to a particular # Note: these tags have no meaning and are not tied to a particular
# libinput version # libinput version
FEDORA_TAG: '2025-05-20.0' FEDORA_TAG: '2025-08-01.0'
DEBIAN_TAG: '2025-05-20.0' DEBIAN_TAG: '2025-08-01.0'
UBUNTU_TAG: '2025-05-20.0' UBUNTU_TAG: '2025-08-01.0'
ARCH_TAG: '2025-05-20.0' ARCH_TAG: '2025-08-01.0'
ALPINE_TAG: '2025-05-20.0' ALPINE_TAG: '2025-08-01.0'
FREEBSD_TAG: '2025-05-20.0' FREEBSD_TAG: '2025-08-01.0'
FDO_UPSTREAM_REPO: libinput/libinput FDO_UPSTREAM_REPO: libinput/libinput

View file

@ -3,7 +3,7 @@
# #
# We're happy to rebuild all containers when one changes. # We're happy to rebuild all containers when one changes.
.default_tag: &default_tag '2025-05-20.0' .default_tag: &default_tag '2025-08-01.0'
distributions: distributions:
- name: fedora - name: fedora
@ -50,7 +50,7 @@ distributions:
- python3-click - python3-click
- python3-rich - python3-rich
- virtme-ng - virtme-ng
- lua-devel - luajit-devel
- name: debian - name: debian
tag: *default_tag tag: *default_tag
versions: versions:
@ -76,7 +76,7 @@ distributions:
- libglib2.0-dev - libglib2.0-dev
- libmtdev-dev - libmtdev-dev
- curl # for the coverity job - curl # for the coverity job
- lua5.4-dev - libluajit-5.1-dev
- name: ubuntu - name: ubuntu
tag: *default_tag tag: *default_tag
versions: versions:
@ -101,7 +101,7 @@ distributions:
- libgtk-3-dev - libgtk-3-dev
- libglib2.0-dev - libglib2.0-dev
- libmtdev-dev - libmtdev-dev
- lua5.4-dev - libluajit-5.1-dev
- name: arch - name: arch
tag: *default_tag tag: *default_tag
versions: versions:
@ -119,7 +119,7 @@ distributions:
- gtk4 - gtk4
- mtdev - mtdev
- diffutils - diffutils
- lua - luajit
build: build:
extra_variables: extra_variables:
- "MESON_ARGS: '-Ddocumentation=false'" # python-recommonmark is no longer in the repos - "MESON_ARGS: '-Ddocumentation=false'" # python-recommonmark is no longer in the repos
@ -140,7 +140,7 @@ distributions:
- gtk4.0-dev - gtk4.0-dev
- mtdev-dev - mtdev-dev
- bash - bash
- lua5.4-dev - luajit-dev
build: build:
extra_variables: extra_variables:
- "MESON_ARGS: '-Ddocumentation=false' # alpine does not have python-recommonmark" - "MESON_ARGS: '-Ddocumentation=false' # alpine does not have python-recommonmark"

View file

@ -9,7 +9,7 @@ of devices. For example, a plugin may add or remove axes and/or buttons on a
device and/or modify the event stream seen by this device before it is passed device and/or modify the event stream seen by this device before it is passed
to libinput. to libinput.
Plugins are implemented in `Lua <https://www.lua.org/>`_ (version 5.4 or later) Plugins are implemented in `Lua <https://www.lua.org/>`_ (version 5.1)
and are typically loaded from ``/usr/lib{64}/libinput/plugins`` and and are typically loaded from ``/usr/lib{64}/libinput/plugins`` and
``/etc/libinput/plugins``. Plugins are loaded in alphabetical order and where ``/etc/libinput/plugins``. Plugins are loaded in alphabetical order and where
multiple plugins share the same file name, the one in the highest precedence multiple plugins share the same file name, the one in the highest precedence
@ -20,7 +20,7 @@ Plugins are run sequentially in ascending sort-order (i.e. ``00-foo.lua`` runs
before ``10-bar.lua``) and each plugin sees the state left by any previous before ``10-bar.lua``) and each plugin sees the state left by any previous
plugins. plugins.
See the `Lua Reference manual <https://www.lua.org/manual/5.4/manual.html>`_ for See the `Lua Reference manual <https://www.lua.org/manual/5.1/manual.html>`_ for
details on the Lua language. details on the Lua language.
.. note:: Plugins are **not** loaded by default, it is up to the compositor .. note:: Plugins are **not** loaded by default, it is up to the compositor

View file

@ -168,8 +168,7 @@ dep_libevdev = dependency('libevdev', version: '>= 1.10.0')
dep_lm = cc.find_library('m', required : false) dep_lm = cc.find_library('m', required : false)
dep_rt = cc.find_library('rt', required : false) dep_rt = cc.find_library('rt', required : false)
dep_lua = dependency('lua-5.4', 'lua5.4', 'lua', dep_lua = dependency(get_option('lua-interpreter'),
version : '>= 5.4',
required : get_option('lua-plugins')) required : get_option('lua-plugins'))
have_lua = dep_lua.found() have_lua = dep_lua.found()
config_h.set10('HAVE_LUA', have_lua) config_h.set10('HAVE_LUA', have_lua)
@ -184,6 +183,11 @@ summary({
section : 'Plugins', section : 'Plugins',
bool_yn : true) bool_yn : true)
if have_lua
summary({'Lua Interpreter' : get_option('lua-interpreter')},
section : 'Plugins')
endif
# Include directories # Include directories
includes_include = include_directories('include') includes_include = include_directories('include')
includes_src = include_directories('src') includes_src = include_directories('src')

View file

@ -46,3 +46,7 @@ option('lua-plugins',
type: 'feature', type: 'feature',
value: 'auto', value: 'auto',
description: 'Enable support for Lua plugins') description: 'Enable support for Lua plugins')
option('lua-interpreter',
type: 'string',
value: 'luajit',
description: 'The Lua interpreter to use (pkgconfig name)')

View file

@ -284,7 +284,18 @@ libinput_lua_pcall(struct libinput_lua_plugin *plugin, int narg, int nres)
{ {
lua_State *L = plugin->L; lua_State *L = plugin->L;
int rc = lua_pcall(L, narg, nres, 0); lua_pushvalue(L, -(narg + 1)); /* Copy the function */
lua_pushvalue(L, plugin->sandbox_table_idx);
/* Now set the sandbox environment for the function we're about to call */
int rc = lua_setfenv(L, -2) == 1 ? LUA_OK : LUA_ERRRUN;
if (rc == LUA_OK) {
/* Replace original function with sandboxed one */
lua_replace(L, -(narg + 2));
/* Now call the function */
rc = lua_pcall(L, narg, nres, 0);
} else {
lua_pushstring(L, "Failed to set up sandbox");
}
if (rc != LUA_OK) { if (rc != LUA_OK) {
auto libinput_plugin = plugin->parent; auto libinput_plugin = plugin->parent;
const char *errormsg = lua_tostring(L, -1); const char *errormsg = lua_tostring(L, -1);
@ -1114,20 +1125,6 @@ libinput_lua_plugin_run(struct libinput_plugin *libinput_plugin)
{ {
struct libinput_lua_plugin *plugin = struct libinput_lua_plugin *plugin =
libinput_plugin_get_user_data(libinput_plugin); libinput_plugin_get_user_data(libinput_plugin);
struct lua_State *L = plugin->L;
/* Main entry point into the plugin, so we need to push our sandbox
* as _ENV. This only needs to be done here because all other entry
* points into the Lua script are callbacks that are set up during
* this run (and thus share the _ENV)
*/
lua_pushvalue(L, plugin->sandbox_table_idx);
const char *upval = lua_setupvalue(L, -2, 1);
if (!upval || !streq(upval, "_ENV")) {
plugin_log_bug_libinput(libinput_plugin, "Failed to set up sandbox\n");
libinput_plugin_unregister(libinput_plugin);
return;
}
if (libinput_lua_pcall(plugin, 0, 0) && !plugin->register_called) { if (libinput_lua_pcall(plugin, 0, 0) && !plugin->register_called) {
plugin_log_bug(libinput_plugin, plugin_log_bug(libinput_plugin,
@ -1214,7 +1211,7 @@ libinput_lua_plugin_init_lua(struct libinput *libinput,
if (!L) if (!L)
return NULL; return NULL;
/* This will be our _ENV later, see libinput_lua_pcall */ /* This will be our our global env later, see libinput_lua_pcall() */
lua_newtable(L); lua_newtable(L);
int sandbox_table_idx = lua_gettop(L); int sandbox_table_idx = lua_gettop(L);
plugin->sandbox_table_idx = sandbox_table_idx; plugin->sandbox_table_idx = sandbox_table_idx;
@ -1227,32 +1224,36 @@ libinput_lua_plugin_init_lua(struct libinput *libinput,
* all have their own individual sandbox. * all have their own individual sandbox.
*/ */
luaL_requiref(L, LUA_GNAME, luaopen_base, 0); luaopen_base(L);
static const char *allowed_funcs[] = { static const char *allowed_funcs[] = {
"assert", "error", "ipairs", "next", "pcall", "pairs", "pairs", "assert", "error", "ipairs", "next", "pcall", "pairs",
"print", "warn", "tonumber", "tostring", "type", "xpcall", "print", "tonumber", "tostring", "type", "unpack", "xpcall",
}; };
ARRAY_FOR_EACH(allowed_funcs, func) { ARRAY_FOR_EACH(allowed_funcs, func) {
lua_getfield(L, -1, *func); lua_getglobal(L, *func);
lua_setfield(L, sandbox_table_idx, *func); lua_setfield(L, sandbox_table_idx, *func);
} }
/* Math is fine as a whole */ /* Math is fine as a whole */
luaL_requiref(L, LUA_MATHLIBNAME, luaopen_math, 0); luaopen_math(L);
lua_getglobal(L, "math");
lua_setfield(L, sandbox_table_idx, "math"); lua_setfield(L, sandbox_table_idx, "math");
/* Table is fine as a whole */ /* Table is fine as a whole */
luaL_requiref(L, LUA_TABLIBNAME, luaopen_table, 0); luaopen_table(L);
lua_getglobal(L, "table");
lua_setfield(L, sandbox_table_idx, "table"); lua_setfield(L, sandbox_table_idx, "table");
/* Table is fine as a whole */ /* String is fine as a whole */
luaL_requiref(L, LUA_STRLIBNAME, luaopen_table, 0); luaopen_string(L);
lua_getglobal(L, "string");
lua_setfield(L, sandbox_table_idx, "string"); lua_setfield(L, sandbox_table_idx, "string");
/* Override metatable to prevent access to unregistered globals */ /* Override metatable to prevent access to unregistered globals */
lua_pushvalue(L, sandbox_table_idx);
lua_newtable(L); lua_newtable(L);
lua_setfield(L, -2, "__index"); lua_pushstring(L, "__index");
lua_pushnil(L);
lua_settable(L, -3);
lua_setmetatable(L, sandbox_table_idx); lua_setmetatable(L, sandbox_table_idx);
/* Our objects */ /* Our objects */
@ -1260,7 +1261,8 @@ libinput_lua_plugin_init_lua(struct libinput *libinput,
evdevdevice_init(L); evdevdevice_init(L);
/* Our globals */ /* Our globals */
luaL_newlib(L, log_funcs); lua_newtable(L);
luaL_register(L, "log", log_funcs);
lua_setfield(L, sandbox_table_idx, "log"); lua_setfield(L, sandbox_table_idx, "log");
libinput_lua_init_evdev_global(L, sandbox_table_idx); libinput_lua_init_evdev_global(L, sandbox_table_idx);