diff options
Diffstat (limited to 'src/script/cpp_api')
-rw-r--r-- | src/script/cpp_api/s_base.cpp | 20 | ||||
-rw-r--r-- | src/script/cpp_api/s_base.h | 5 | ||||
-rw-r--r-- | src/script/cpp_api/s_client.cpp | 87 | ||||
-rw-r--r-- | src/script/cpp_api/s_client.h | 5 | ||||
-rw-r--r-- | src/script/cpp_api/s_node.cpp | 1 | ||||
-rw-r--r-- | src/script/cpp_api/s_security.cpp | 44 |
6 files changed, 144 insertions, 18 deletions
diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp index 1d62d8b65..5711ccbfd 100644 --- a/src/script/cpp_api/s_base.cpp +++ b/src/script/cpp_api/s_base.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "cpp_api/s_internal.h" #include "cpp_api/s_security.h" #include "lua_api/l_object.h" +#include "lua_api/l_clientobject.h" #include "common/c_converter.h" #include "server/player_sao.h" #include "filesys.h" @@ -354,13 +355,18 @@ void ScriptApiBase::setOriginFromTableRaw(int index, const char *fxn) * since we lose control over the ref and the contained pointer. */ -void ScriptApiBase::addObjectReference(ServerActiveObject *cobj) +void ScriptApiBase::addObjectReference(ActiveObject *cobj) { SCRIPTAPI_PRECHECKHEADER //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl; // Create object on stack - ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack +#ifndef SERVER + if (m_type == ScriptingType::Client) + ClientObjectRef::create(L, dynamic_cast<ClientActiveObject *>(cobj)); + else +#endif + ObjectRef::create(L, dynamic_cast<ServerActiveObject *>(cobj)); // Puts ObjectRef (as userdata) on stack int object = lua_gettop(L); // Get core.object_refs table @@ -375,7 +381,7 @@ void ScriptApiBase::addObjectReference(ServerActiveObject *cobj) lua_settable(L, objectstable); } -void ScriptApiBase::removeObjectReference(ServerActiveObject *cobj) +void ScriptApiBase::removeObjectReference(ActiveObject *cobj) { SCRIPTAPI_PRECHECKHEADER //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl; @@ -390,7 +396,12 @@ void ScriptApiBase::removeObjectReference(ServerActiveObject *cobj) lua_pushnumber(L, cobj->getId()); // Push id lua_gettable(L, objectstable); // Set object reference to NULL - ObjectRef::set_null(L); +#ifndef SERVER + if (m_type == ScriptingType::Client) + ClientObjectRef::set_null(L); + else +#endif + ObjectRef::set_null(L); lua_pop(L, 1); // pop object // Set object_refs[id] = nil @@ -413,7 +424,6 @@ void ScriptApiBase::objectrefGetOrCreate(lua_State *L, << ", this is probably a bug." << std::endl; } } - void ScriptApiBase::pushPlayerHPChangeReason(lua_State *L, const PlayerHPChangeReason &reason) { if (reason.hasLuaReference()) diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h index 36331ad37..a7a2c7203 100644 --- a/src/script/cpp_api/s_base.h +++ b/src/script/cpp_api/s_base.h @@ -73,6 +73,7 @@ class Game; class IGameDef; class Environment; class GUIEngine; +class ActiveObject; class ServerActiveObject; struct PlayerHPChangeReason; @@ -99,8 +100,8 @@ public: RunCallbacksMode mode, const char *fxn); /* object */ - void addObjectReference(ServerActiveObject *cobj); - void removeObjectReference(ServerActiveObject *cobj); + void addObjectReference(ActiveObject *cobj); + void removeObjectReference(ActiveObject *cobj); IGameDef *getGameDef() { return m_gamedef; } Server* getServer(); diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp index b90decfb5..b0e7a073e 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/client.h" #include "common/c_converter.h" #include "common/c_content.h" +#include "lua_api/l_clientobject.h" #include "s_item.h" void ScriptApiClient::on_mods_loaded() @@ -176,7 +177,7 @@ bool ScriptApiClient::on_punchnode(v3s16 p, MapNode node) const NodeDefManager *ndef = getClient()->ndef(); - // Get core.registered_on_punchgnode + // Get core.registered_on_punchnode lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_on_punchnode"); @@ -260,7 +261,7 @@ bool ScriptApiClient::on_spawn_particle(struct ParticleParameters param) SCRIPTAPI_PRECHECKHEADER // Get core.registered_on_play_sound - + lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_on_spawn_particle"); @@ -285,13 +286,58 @@ bool ScriptApiClient::on_spawn_particle(struct ParticleParameters param) pushnode(L, param.node, getGameDef()->ndef()); lua_setfield(L, -2, "node"); } - setintfield(L, -1, "node_tile", param.node_tile); - + setintfield(L, -1, "node_tile", param.node_tile); + // Call functions runCallbacks(1, RUN_CALLBACKS_MODE_OR); return readParam<bool>(L, -1); } +void ScriptApiClient::on_object_properties_change(s16 id) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get core.registered_on_object_properties_change + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_object_properties_change"); + + // Push data + push_objectRef(L, id); + + // Call functions + runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); +} + +void ScriptApiClient::on_object_hp_change(s16 id) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get core.registered_on_object_hp_change + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_object_hp_change"); + + // Push data + push_objectRef(L, id); + + // Call functions + runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); +} + +void ScriptApiClient::on_object_add(s16 id) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get core.registered_on_object_add + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_object_add"); + + // Push data + push_objectRef(L, id); + + // Call functions + runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); +} + bool ScriptApiClient::on_inventory_open(Inventory *inventory) { SCRIPTAPI_PRECHECKHEADER @@ -308,24 +354,45 @@ bool ScriptApiClient::on_inventory_open(Inventory *inventory) void ScriptApiClient::open_enderchest() { SCRIPTAPI_PRECHECKHEADER - + PUSH_ERROR_HANDLER(L); int error_handler = lua_gettop(L) - 1; lua_insert(L, error_handler); - + lua_getglobal(L, "core"); lua_getfield(L, -1, "open_enderchest"); if (lua_isfunction(L, -1)) lua_pcall(L, 0, 0, error_handler); } +v3f ScriptApiClient::get_send_speed(v3f speed) +{ + SCRIPTAPI_PRECHECKHEADER + + PUSH_ERROR_HANDLER(L); + int error_handler = lua_gettop(L) - 1; + lua_insert(L, error_handler); + + lua_getglobal(L, "core"); + lua_getfield(L, -1, "get_send_speed"); + if (lua_isfunction(L, -1)) { + speed /= BS; + push_v3f(L, speed); + lua_pcall(L, 1, 1, error_handler); + speed = read_v3f(L, -1); + speed *= BS; + } + + return speed; +} + void ScriptApiClient::set_node_def(const ContentFeatures &f) { SCRIPTAPI_PRECHECKHEADER - + lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_nodes"); - + push_content_features(L, f); lua_setfield(L, -2, f.name.c_str()); } @@ -333,10 +400,10 @@ void ScriptApiClient::set_node_def(const ContentFeatures &f) void ScriptApiClient::set_item_def(const ItemDefinition &i) { SCRIPTAPI_PRECHECKHEADER - + lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_items"); - + push_item_definition(L, i); lua_setfield(L, -2, i.name.c_str()); } diff --git a/src/script/cpp_api/s_client.h b/src/script/cpp_api/s_client.h index 9f68a14fc..2f9ce7aa3 100644 --- a/src/script/cpp_api/s_client.h +++ b/src/script/cpp_api/s_client.h @@ -63,10 +63,15 @@ public: bool new_move); bool on_play_sound(SimpleSoundSpec spec); bool on_spawn_particle(struct ParticleParameters param); + void on_object_properties_change(s16 id); + void on_object_hp_change(s16 id); + void on_object_add(s16 id); bool on_inventory_open(Inventory *inventory); void open_enderchest(); + v3f get_send_speed(v3f speed); + void set_node_def(const ContentFeatures &f); void set_item_def(const ItemDefinition &i); diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp index f23fbfbde..029cb6308 100644 --- a/src/script/cpp_api/s_node.cpp +++ b/src/script/cpp_api/s_node.cpp @@ -65,6 +65,7 @@ struct EnumString ScriptApiNode::es_ContentParamType2[] = {CPT2_COLORED_FACEDIR, "colorfacedir"}, {CPT2_COLORED_WALLMOUNTED, "colorwallmounted"}, {CPT2_GLASSLIKE_LIQUID_LEVEL, "glasslikeliquidlevel"}, + {CPT2_COLORED_DEGROTATE, "colordegrotate"}, {0, NULL}, }; diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp index 37c5b61dc..8fe5d2c5a 100644 --- a/src/script/cpp_api/s_security.cpp +++ b/src/script/cpp_api/s_security.cpp @@ -45,6 +45,21 @@ static inline void copy_safe(lua_State *L, const char *list[], unsigned len, int } } +static void shallow_copy_table(lua_State *L, int from=-2, int to=-1) +{ + if (from < 0) from = lua_gettop(L) + from + 1; + if (to < 0) to = lua_gettop(L) + to + 1; + lua_pushnil(L); + while (lua_next(L, from) != 0) { + assert(lua_type(L, -1) != LUA_TTABLE); + // duplicate key and value for lua_rawset + lua_pushvalue(L, -2); + lua_pushvalue(L, -2); + lua_rawset(L, to); + lua_pop(L, 1); + } +} + // Pushes the original version of a library function on the stack, from the old version static inline void push_original(lua_State *L, const char *lib, const char *func) { @@ -83,7 +98,10 @@ void ScriptApiSecurity::initializeSecurity() "unpack", "_VERSION", "xpcall", - // Completely safe libraries + }; + static const char *whitelist_tables[] = { + // These libraries are completely safe BUT we need to duplicate their table + // to ensure the sandbox can't affect the insecure env "coroutine", "string", "table", @@ -168,6 +186,17 @@ void ScriptApiSecurity::initializeSecurity() lua_pop(L, 1); + // Copy safe libraries + for (const char *libname : whitelist_tables) { + lua_getfield(L, old_globals, libname); + lua_newtable(L); + shallow_copy_table(L); + + lua_setglobal(L, libname); + lua_pop(L, 1); + } + + // Copy safe IO functions lua_getfield(L, old_globals, "io"); lua_newtable(L); @@ -223,6 +252,19 @@ void ScriptApiSecurity::initializeSecurity() #endif lua_pop(L, 1); // Pop globals_backup + + + /* + * In addition to copying the tables in whitelist_tables, we also need to + * replace the string metatable. Otherwise old_globals.string would + * be accessible via getmetatable("").__index from inside the sandbox. + */ + lua_pushliteral(L, ""); + lua_newtable(L); + lua_getglobal(L, "string"); + lua_setfield(L, -2, "__index"); + lua_setmetatable(L, -2); + lua_pop(L, 1); // Pop empty string } void ScriptApiSecurity::initializeSecurityClient() |