Lua: fix: ReadOnlyTable, existing keys could be written
Dieser Commit ist enthalten in:
Ursprung
919e2e2787
Commit
d9b121948f
@ -54,7 +54,7 @@ void Console::push(lua_State* L)
|
||||
lua_pushcfunction(L, fatal);
|
||||
lua_setfield(L, -2, "fatal");
|
||||
|
||||
ReadOnlyTable::setMetatable(L, -1);
|
||||
ReadOnlyTable::wrap(L, -1);
|
||||
}
|
||||
|
||||
void Console::log(lua_State* L, ::Console::Level level, const std::string& message)
|
||||
|
||||
@ -98,7 +98,7 @@ struct Enum
|
||||
push(L, it.first);
|
||||
lua_setfield(L, -2, toUpper(it.second).c_str());
|
||||
}
|
||||
ReadOnlyTable::setMetatable(L, -1);
|
||||
ReadOnlyTable::wrap(L, -1);
|
||||
lua_setfield(L, -2, EnumName<T>::value);
|
||||
}
|
||||
};
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019-2020 Reinder Feenstra
|
||||
* Copyright (C) 2019-2021 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -29,28 +29,32 @@
|
||||
|
||||
namespace Lua {
|
||||
|
||||
struct ReadOnlyTable
|
||||
class ReadOnlyTable
|
||||
{
|
||||
static constexpr const char* metatableName = "read_only_table";
|
||||
|
||||
static void setMetatable(lua_State* L, int index)
|
||||
{
|
||||
luaL_getmetatable(L, metatableName);
|
||||
assert(lua_istable(L, -1)); // is type registered?
|
||||
lua_setmetatable(L, index < 0 ? index - 1 : index);
|
||||
}
|
||||
|
||||
private:
|
||||
static int __newindex(lua_State* L)
|
||||
{
|
||||
errorTableIsReadOnly(L);
|
||||
}
|
||||
|
||||
static void registerType(lua_State* L)
|
||||
public:
|
||||
static void wrap(lua_State* L, int index)
|
||||
{
|
||||
luaL_newmetatable(L, metatableName);
|
||||
assert(lua_istable(L, index));
|
||||
lua_newtable(L); // create wrapper table
|
||||
lua_newtable(L); // metatable for wrapper table
|
||||
if(index < 0)
|
||||
index -= 2; // correct index if relative
|
||||
lua_pushvalue(L, index); // copy source table (ref)
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pushcfunction(L, __newindex);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pop(L, 1);
|
||||
lua_pushboolean(L, 0);
|
||||
lua_setfield(L, -2, "__metatable");
|
||||
lua_setmetatable(L, -2); // set metatable @ wrapper table
|
||||
if(index < 0)
|
||||
index++; // correct index if relative
|
||||
lua_replace(L, index); // replace source table by wrapper table
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -98,13 +98,13 @@ SandboxPtr Sandbox::create(Script& script)
|
||||
Enum<DecoderProtocol>::registerValues(L);
|
||||
Enum<Direction>::registerValues(L);
|
||||
Enum<WorldEvent>::registerValues(L);
|
||||
ReadOnlyTable::setMetatable(L, -1);
|
||||
ReadOnlyTable::wrap(L, -1);
|
||||
lua_setfield(L, -2, "enum");
|
||||
|
||||
// add set values:
|
||||
lua_newtable(L);
|
||||
Set<WorldState>::registerValues(L);
|
||||
ReadOnlyTable::setMetatable(L, -1);
|
||||
ReadOnlyTable::wrap(L, -1);
|
||||
lua_setfield(L, -2, "set");
|
||||
|
||||
// let global _G point to itself:
|
||||
|
||||
@ -174,7 +174,7 @@ struct Set
|
||||
push(L, it.first);
|
||||
lua_setfield(L, -2, it.second);
|
||||
}
|
||||
ReadOnlyTable::setMetatable(L, -1);
|
||||
ReadOnlyTable::wrap(L, -1);
|
||||
lua_setfield(L, -2, set_name_v<T>);
|
||||
}
|
||||
};
|
||||
|
||||
@ -37,7 +37,6 @@ static lua_State* createState()
|
||||
{
|
||||
lua_State* L = newStateWithProtect();
|
||||
|
||||
Lua::ReadOnlyTable::registerType(L);
|
||||
Lua::Enum<T>::registerType(L);
|
||||
|
||||
lua_createtable(L, 0, 1);
|
||||
|
||||
@ -35,7 +35,6 @@ static lua_State* createState()
|
||||
{
|
||||
lua_State* L = newStateWithProtect();
|
||||
|
||||
Lua::ReadOnlyTable::registerType(L);
|
||||
Lua::Set<T>::registerType(L);
|
||||
|
||||
lua_createtable(L, 0, 1);
|
||||
|
||||
Laden…
x
In neuem Issue referenzieren
Einen Benutzer sperren