* @brief Opens the safe Lua libraries needed by transforms and strips dangerous globals, including * string.dump whose bytecode serialization paired with a loader is a sandbox-escape vector. */
| 1897 | * string.dump whose bytecode serialization paired with a loader is a sandbox-escape vector. |
| 1898 | */ |
| 1899 | static void openSafeLibsForTransform(lua_State* L) |
| 1900 | { |
| 1901 | static const luaL_Reg kSafeLibs[] = { |
| 1902 | { "_G", luaopen_base}, |
| 1903 | { "table", luaopen_table}, |
| 1904 | { "string", luaopen_string}, |
| 1905 | { "math", luaopen_math}, |
| 1906 | { "utf8", luaopen_utf8}, |
| 1907 | {"coroutine", luaopen_coroutine}, |
| 1908 | { nullptr, nullptr} |
| 1909 | }; |
| 1910 | |
| 1911 | for (const luaL_Reg* lib = kSafeLibs; lib->func; ++lib) { |
| 1912 | luaL_requiref(L, lib->name, lib->func, 1); |
| 1913 | lua_pop(L, 1); |
| 1914 | } |
| 1915 | |
| 1916 | for (const char* name : {"dofile", "loadfile", "load"}) { |
| 1917 | lua_pushnil(L); |
| 1918 | lua_setglobal(L, name); |
| 1919 | } |
| 1920 | |
| 1921 | lua_getglobal(L, "string"); |
| 1922 | if (lua_istable(L, -1)) { |
| 1923 | lua_pushnil(L); |
| 1924 | lua_setfield(L, -2, "dump"); |
| 1925 | } |
| 1926 | lua_pop(L, 1); |
| 1927 | } |
| 1928 | |
| 1929 | /** |
| 1930 | * @brief Lua LUA_MASKCOUNT hook that aborts runaway transforms via luaL_error() when the per-engine |
no test coverage detected