lua: made built-in globals read only
Dieser Commit ist enthalten in:
Ursprung
b6ec6cc8bd
Commit
906ff82cd8
@ -42,7 +42,9 @@ namespace Lua {
|
||||
|
||||
[[noreturn]] inline void errorExpectedNArgumentsGotN(lua_State* L, int expected, int got) { luaL_error(L, "expected %d arguments, got %d", expected, got); abort(); }
|
||||
|
||||
[[noreturn]] inline void errorException(lua_State* L, const std::exception& e) { luaL_error(L, "exceptiop: %s", e.what()); abort(); }
|
||||
[[noreturn]] inline void errorException(lua_State* L, const std::exception& e) { luaL_error(L, "exception: %s", e.what()); abort(); }
|
||||
|
||||
[[noreturn]] inline void errorGlobalNIsReadOnly(lua_State* L, const char* name) { luaL_error(L, "global %s is readonly", name); abort(); }
|
||||
|
||||
[[noreturn]] inline void errorInternal(lua_State* L) { luaL_error(L, "internal error"); abort(); }
|
||||
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include "method.hpp"
|
||||
#include "log.hpp"
|
||||
#include "class.hpp"
|
||||
#include "to.hpp"
|
||||
#include <version.hpp>
|
||||
#include <traintastic/utils/str.hpp>
|
||||
#include <traintastic/codename.hpp>
|
||||
@ -37,12 +38,38 @@
|
||||
#include "../set/worldstate.hpp"
|
||||
|
||||
#define LUA_SANDBOX "_sandbox"
|
||||
#define LUA_SANDBOX_GLOBALS "_sandbox_globals"
|
||||
|
||||
#define ADD_GLOBAL_TO_SANDBOX(x) \
|
||||
lua_pushliteral(L, x); \
|
||||
lua_getglobal(L, x); \
|
||||
lua_settable(L, -3);
|
||||
|
||||
constexpr std::array<std::string_view, 17> readOnlyGlobals = {{
|
||||
// Lua baselib:
|
||||
"assert",
|
||||
"type",
|
||||
"pairs",
|
||||
"ipairs",
|
||||
"_G",
|
||||
// Constants:
|
||||
"VERSION",
|
||||
"VERSION_MAJOR",
|
||||
"VERSION_MINOR",
|
||||
"VERSION_PATCH",
|
||||
"CODENAME",
|
||||
"LUA_VERSION",
|
||||
// Objects:
|
||||
"world",
|
||||
"log",
|
||||
// Functions:
|
||||
"is_instance",
|
||||
// Type info:
|
||||
"class",
|
||||
"enum",
|
||||
"set",
|
||||
}};
|
||||
|
||||
namespace Lua {
|
||||
|
||||
void Sandbox::close(lua_State* L)
|
||||
@ -51,6 +78,29 @@ void Sandbox::close(lua_State* L)
|
||||
lua_close(L);
|
||||
}
|
||||
|
||||
int Sandbox::__index(lua_State* L)
|
||||
{
|
||||
lua_getglobal(L, LUA_SANDBOX_GLOBALS);
|
||||
lua_replace(L, 1);
|
||||
|
||||
lua_rawget(L, 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Sandbox::__newindex(lua_State* L)
|
||||
{
|
||||
if(std::find(readOnlyGlobals.begin(), readOnlyGlobals.end(), to<std::string_view>(L, 2)) != readOnlyGlobals.end())
|
||||
errorGlobalNIsReadOnly(L, lua_tostring(L, 2));
|
||||
|
||||
lua_getglobal(L, LUA_SANDBOX_GLOBALS);
|
||||
lua_replace(L, 1);
|
||||
|
||||
lua_rawset(L, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SandboxPtr Sandbox::create(Script& script)
|
||||
{
|
||||
lua_State* L = luaL_newstate();
|
||||
@ -74,6 +124,16 @@ SandboxPtr Sandbox::create(Script& script)
|
||||
|
||||
// setup sandbox:
|
||||
lua_newtable(L);
|
||||
luaL_newmetatable(L, LUA_SANDBOX);
|
||||
lua_pushcfunction(L, __index);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pushcfunction(L, __newindex);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, LUA_SANDBOX);
|
||||
|
||||
// setup globals:
|
||||
lua_newtable(L);
|
||||
|
||||
// add some Lua baselib functions to the sandbox:
|
||||
ADD_GLOBAL_TO_SANDBOX("assert")
|
||||
@ -133,12 +193,11 @@ SandboxPtr Sandbox::create(Script& script)
|
||||
ReadOnlyTable::wrap(L, -1);
|
||||
lua_setfield(L, -2, "set");
|
||||
|
||||
// let global _G point to itself:
|
||||
lua_pushliteral(L, "_G");
|
||||
lua_pushvalue(L, -2);
|
||||
lua_settable(L, -3);
|
||||
// let global _G point to the sandbox:
|
||||
lua_getglobal(L, LUA_SANDBOX);
|
||||
lua_setfield(L, -2, "_G");
|
||||
|
||||
lua_setglobal(L, LUA_SANDBOX);
|
||||
lua_setglobal(L, LUA_SANDBOX_GLOBALS);
|
||||
|
||||
return SandboxPtr(L, close);
|
||||
}
|
||||
|
||||
@ -36,6 +36,8 @@ class Sandbox
|
||||
{
|
||||
private:
|
||||
static void close(lua_State* L);
|
||||
static int __index(lua_State* L);
|
||||
static int __newindex(lua_State* L);
|
||||
|
||||
public:
|
||||
class StateData
|
||||
|
||||
Laden…
x
In neuem Issue referenzieren
Einen Benutzer sperren