// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details // This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details #include "lualib.h" #include static const luaL_Reg lualibs[] = { {"", luaopen_base}, {LUA_COLIBNAME, luaopen_coroutine}, {LUA_TABLIBNAME, luaopen_table}, {LUA_OSLIBNAME, luaopen_os}, {LUA_STRLIBNAME, luaopen_string}, {LUA_MATHLIBNAME, luaopen_math}, {LUA_DBLIBNAME, luaopen_debug}, {LUA_UTF8LIBNAME, luaopen_utf8}, {LUA_BITLIBNAME, luaopen_bit32}, {NULL, NULL}, }; void luaL_openlibs(lua_State* L) { const luaL_Reg* lib = lualibs; for (; lib->func; lib++) { lua_pushcfunction(L, lib->func, NULL); lua_pushstring(L, lib->name); lua_call(L, 1, 0); } } void luaL_sandbox(lua_State* L) { // set all libraries to read-only lua_pushnil(L); while (lua_next(L, LUA_GLOBALSINDEX) != 0) { if (lua_istable(L, -1)) lua_setreadonly(L, -1, true); lua_pop(L, 1); } // set all builtin metatables to read-only lua_pushliteral(L, ""); lua_getmetatable(L, -1); lua_setreadonly(L, -1, true); lua_pop(L, 2); // set globals to readonly and activate safeenv since the env is immutable lua_setreadonly(L, LUA_GLOBALSINDEX, true); lua_setsafeenv(L, LUA_GLOBALSINDEX, true); } void luaL_sandboxthread(lua_State* L) { // create new global table that proxies reads to original table lua_newtable(L); lua_newtable(L); lua_pushvalue(L, LUA_GLOBALSINDEX); lua_setfield(L, -2, "__index"); lua_setreadonly(L, -1, true); lua_setmetatable(L, -2); // we can set safeenv now although it's important to set it to false if code is loaded twice into the thread lua_replace(L, LUA_GLOBALSINDEX); lua_setsafeenv(L, LUA_GLOBALSINDEX, true); } static void* l_alloc(void* ud, void* ptr, size_t osize, size_t nsize) { (void)ud; (void)osize; if (nsize == 0) { free(ptr); return NULL; } else return realloc(ptr, nsize); } lua_State* luaL_newstate(void) { return lua_newstate(l_alloc, NULL); }