Lua: fix: ReadOnlyTable, existing keys could be written

Dieser Commit ist enthalten in:
Reinder Feenstra 2021-04-22 23:28:41 +02:00
Ursprung 919e2e2787
Commit d9b121948f
7 geänderte Dateien mit 31 neuen und 29 gelöschten Zeilen

Datei anzeigen

@ -54,7 +54,7 @@ void Console::push(lua_State* L)
lua_pushcfunction(L, fatal); lua_pushcfunction(L, fatal);
lua_setfield(L, -2, "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) void Console::log(lua_State* L, ::Console::Level level, const std::string& message)

Datei anzeigen

@ -98,7 +98,7 @@ struct Enum
push(L, it.first); push(L, it.first);
lua_setfield(L, -2, toUpper(it.second).c_str()); lua_setfield(L, -2, toUpper(it.second).c_str());
} }
ReadOnlyTable::setMetatable(L, -1); ReadOnlyTable::wrap(L, -1);
lua_setfield(L, -2, EnumName<T>::value); lua_setfield(L, -2, EnumName<T>::value);
} }
}; };

Datei anzeigen

@ -3,7 +3,7 @@
* *
* This file is part of the traintastic source code. * 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -29,29 +29,33 @@
namespace Lua { namespace Lua {
struct ReadOnlyTable class ReadOnlyTable
{ {
static constexpr const char* metatableName = "read_only_table"; private:
static int __newindex(lua_State* L)
{
errorTableIsReadOnly(L);
}
static void setMetatable(lua_State* L, int index) public:
{ static void wrap(lua_State* L, int index)
luaL_getmetatable(L, metatableName); {
assert(lua_istable(L, -1)); // is type registered? assert(lua_istable(L, index));
lua_setmetatable(L, index < 0 ? index - 1 : index); lua_newtable(L); // create wrapper table
} lua_newtable(L); // metatable for wrapper table
if(index < 0)
static int __newindex(lua_State* L) index -= 2; // correct index if relative
{ lua_pushvalue(L, index); // copy source table (ref)
errorTableIsReadOnly(L); lua_setfield(L, -2, "__index");
} lua_pushcfunction(L, __newindex);
lua_setfield(L, -2, "__newindex");
static void registerType(lua_State* L) lua_pushboolean(L, 0);
{ lua_setfield(L, -2, "__metatable");
luaL_newmetatable(L, metatableName); lua_setmetatable(L, -2); // set metatable @ wrapper table
lua_pushcfunction(L, __newindex); if(index < 0)
lua_setfield(L, -2, "__newindex"); index++; // correct index if relative
lua_pop(L, 1); lua_replace(L, index); // replace source table by wrapper table
} }
}; };
} }

Datei anzeigen

@ -98,13 +98,13 @@ SandboxPtr Sandbox::create(Script& script)
Enum<DecoderProtocol>::registerValues(L); Enum<DecoderProtocol>::registerValues(L);
Enum<Direction>::registerValues(L); Enum<Direction>::registerValues(L);
Enum<WorldEvent>::registerValues(L); Enum<WorldEvent>::registerValues(L);
ReadOnlyTable::setMetatable(L, -1); ReadOnlyTable::wrap(L, -1);
lua_setfield(L, -2, "enum"); lua_setfield(L, -2, "enum");
// add set values: // add set values:
lua_newtable(L); lua_newtable(L);
Set<WorldState>::registerValues(L); Set<WorldState>::registerValues(L);
ReadOnlyTable::setMetatable(L, -1); ReadOnlyTable::wrap(L, -1);
lua_setfield(L, -2, "set"); lua_setfield(L, -2, "set");
// let global _G point to itself: // let global _G point to itself:

Datei anzeigen

@ -174,7 +174,7 @@ struct Set
push(L, it.first); push(L, it.first);
lua_setfield(L, -2, it.second); lua_setfield(L, -2, it.second);
} }
ReadOnlyTable::setMetatable(L, -1); ReadOnlyTable::wrap(L, -1);
lua_setfield(L, -2, set_name_v<T>); lua_setfield(L, -2, set_name_v<T>);
} }
}; };

Datei anzeigen

@ -37,7 +37,6 @@ static lua_State* createState()
{ {
lua_State* L = newStateWithProtect(); lua_State* L = newStateWithProtect();
Lua::ReadOnlyTable::registerType(L);
Lua::Enum<T>::registerType(L); Lua::Enum<T>::registerType(L);
lua_createtable(L, 0, 1); lua_createtable(L, 0, 1);

Datei anzeigen

@ -35,7 +35,6 @@ static lua_State* createState()
{ {
lua_State* L = newStateWithProtect(); lua_State* L = newStateWithProtect();
Lua::ReadOnlyTable::registerType(L);
Lua::Set<T>::registerType(L); Lua::Set<T>::registerType(L);
lua_createtable(L, 0, 1); lua_createtable(L, 0, 1);