diff options
Diffstat (limited to 'src/script/cpp_api')
-rw-r--r-- | src/script/cpp_api/s_base.cpp | 30 | ||||
-rw-r--r-- | src/script/cpp_api/s_item.cpp | 5 | ||||
-rw-r--r-- | src/script/cpp_api/s_item.h | 3 | ||||
-rw-r--r-- | src/script/cpp_api/s_security.cpp | 93 | ||||
-rw-r--r-- | src/script/cpp_api/s_security.h | 2 |
5 files changed, 65 insertions, 68 deletions
diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp index caa335d76..ecb1ba39b 100644 --- a/src/script/cpp_api/s_base.cpp +++ b/src/script/cpp_api/s_base.cpp @@ -197,18 +197,22 @@ void ScriptApiBase::loadModFromMemory(const std::string &mod_name) { ModNameStorer mod_name_storer(getStack(), mod_name); - const std::string *init_filename = getClient()->getModFile(mod_name + ":init.lua"); - const std::string display_filename = mod_name + ":init.lua"; - if(init_filename == NULL) - throw ModError("Mod:\"" + mod_name + "\" lacks init.lua"); + sanity_check(m_type == ScriptingType::Client); - verbosestream << "Loading and running script " << display_filename << std::endl; + const std::string init_filename = mod_name + ":init.lua"; + const std::string chunk_name = "@" + init_filename; + + const std::string *contents = getClient()->getModFile(init_filename); + if (!contents) + throw ModError("Mod \"" + mod_name + "\" lacks init.lua"); + + verbosestream << "Loading and running script " << chunk_name << std::endl; lua_State *L = getStack(); int error_handler = PUSH_ERROR_HANDLER(L); - bool ok = ScriptApiSecurity::safeLoadFile(L, init_filename->c_str(), display_filename.c_str()); + bool ok = ScriptApiSecurity::safeLoadString(L, *contents, chunk_name.c_str()); if (ok) ok = !lua_pcall(L, 0, 0, error_handler); if (!ok) { @@ -329,6 +333,20 @@ void ScriptApiBase::setOriginFromTableRaw(int index, const char *fxn) #endif } +/* + * How ObjectRefs are handled in Lua: + * When an active object is created, an ObjectRef is created on the Lua side + * and stored in core.object_refs[id]. + * Methods that require an ObjectRef to a certain object retrieve it from that + * table instead of creating their own.(*) + * When an active object is removed, the existing ObjectRef is invalidated + * using ::set_null() and removed from the core.object_refs table. + * (*) An exception to this are NULL ObjectRefs and anonymous ObjectRefs + * for objects without ID. + * It's unclear what the latter are needed for and their use is problematic + * since we lose control over the ref and the contained pointer. + */ + void ScriptApiBase::addObjectReference(ServerActiveObject *cobj) { SCRIPTAPI_PRECHECKHEADER diff --git a/src/script/cpp_api/s_item.cpp b/src/script/cpp_api/s_item.cpp index cbdfcf1b1..24955cefc 100644 --- a/src/script/cpp_api/s_item.cpp +++ b/src/script/cpp_api/s_item.cpp @@ -115,7 +115,8 @@ bool ScriptApiItem::item_OnUse(ItemStack &item, return true; } -bool ScriptApiItem::item_OnSecondaryUse(ItemStack &item, ServerActiveObject *user) +bool ScriptApiItem::item_OnSecondaryUse(ItemStack &item, + ServerActiveObject *user, const PointedThing &pointed) { SCRIPTAPI_PRECHECKHEADER @@ -126,8 +127,6 @@ bool ScriptApiItem::item_OnSecondaryUse(ItemStack &item, ServerActiveObject *use LuaItemStack::create(L, item); objectrefGetOrCreate(L, user); - PointedThing pointed; - pointed.type = POINTEDTHING_NOTHING; pushPointedThing(pointed); PCALL_RES(lua_pcall(L, 3, 1, error_handler)); if (!lua_isnil(L, -1)) { diff --git a/src/script/cpp_api/s_item.h b/src/script/cpp_api/s_item.h index 6c7f286a9..25a3501f9 100644 --- a/src/script/cpp_api/s_item.h +++ b/src/script/cpp_api/s_item.h @@ -42,7 +42,7 @@ public: bool item_OnUse(ItemStack &item, ServerActiveObject *user, const PointedThing &pointed); bool item_OnSecondaryUse(ItemStack &item, - ServerActiveObject *user); + ServerActiveObject *user, const PointedThing &pointed); bool item_OnCraft(ItemStack &item, ServerActiveObject *user, const InventoryList *old_craft_grid, const InventoryLocation &craft_inv); bool item_CraftPredict(ItemStack &item, ServerActiveObject *user, @@ -51,7 +51,6 @@ public: protected: friend class LuaItemStack; friend class ModApiItemMod; - friend class LuaRaycast; bool getItemCallback(const char *name, const char *callbackname, const v3s16 *p = nullptr); /*! diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp index b90b3aa2c..b5abcfb5d 100644 --- a/src/script/cpp_api/s_security.cpp +++ b/src/script/cpp_api/s_security.cpp @@ -372,14 +372,16 @@ bool ScriptApiSecurity::isSecure(lua_State *L) return secure; } - -#define CHECK_FILE_ERR(ret, fp) \ - if (ret) { \ - lua_pushfstring(L, "%s: %s", path, strerror(errno)); \ - if (fp) std::fclose(fp); \ - return false; \ +bool ScriptApiSecurity::safeLoadString(lua_State *L, const std::string &code, const char *chunk_name) +{ + if (code.size() > 0 && code[0] == LUA_SIGNATURE[0]) { + lua_pushliteral(L, "Bytecode prohibited when mod security is enabled."); + return false; } - + if (luaL_loadbuffer(L, code.data(), code.size(), chunk_name)) + return false; + return true; +} bool ScriptApiSecurity::safeLoadFile(lua_State *L, const char *path, const char *display_name) { @@ -406,68 +408,49 @@ bool ScriptApiSecurity::safeLoadFile(lua_State *L, const char *path, const char int c = std::getc(fp); if (c == '#') { // Skip the first line - while ((c = std::getc(fp)) != EOF && c != '\n'); - if (c == '\n') c = std::getc(fp); + while ((c = std::getc(fp)) != EOF && c != '\n') {} + if (c == '\n') + std::getc(fp); start = std::ftell(fp); } - if (c == LUA_SIGNATURE[0]) { - lua_pushliteral(L, "Bytecode prohibited when mod security is enabled."); - std::fclose(fp); - if (path) { - delete [] chunk_name; - } - return false; - } - // Read the file int ret = std::fseek(fp, 0, SEEK_END); if (ret) { lua_pushfstring(L, "%s: %s", path, strerror(errno)); - std::fclose(fp); if (path) { + std::fclose(fp); delete [] chunk_name; } return false; } size_t size = std::ftell(fp) - start; - char *code = new char[size]; + std::string code(size, '\0'); ret = std::fseek(fp, start, SEEK_SET); if (ret) { lua_pushfstring(L, "%s: %s", path, strerror(errno)); - std::fclose(fp); - delete [] code; if (path) { + std::fclose(fp); delete [] chunk_name; } return false; } - size_t num_read = std::fread(code, 1, size, fp); - if (path) { + size_t num_read = std::fread(&code[0], 1, size, fp); + if (path) std::fclose(fp); - } if (num_read != size) { lua_pushliteral(L, "Error reading file to load."); - delete [] code; - if (path) { + if (path) delete [] chunk_name; - } return false; } - if (luaL_loadbuffer(L, code, size, chunk_name)) { - delete [] code; - return false; - } - - delete [] code; - - if (path) { + bool result = safeLoadString(L, code, chunk_name); + if (path) delete [] chunk_name; - } - return true; + return result; } @@ -628,14 +611,9 @@ int ScriptApiSecurity::sl_g_load(lua_State *L) code += std::string(buf, len); lua_pop(L, 1); // Pop return value } - if (code[0] == LUA_SIGNATURE[0]) { + if (!safeLoadString(L, code, chunk_name)) { lua_pushnil(L); - lua_pushliteral(L, "Bytecode prohibited when mod security is enabled."); - return 2; - } - if (luaL_loadbuffer(L, code.data(), code.size(), chunk_name)) { - lua_pushnil(L); - lua_insert(L, lua_gettop(L) - 1); + lua_insert(L, -2); return 2; } return 1; @@ -649,16 +627,19 @@ int ScriptApiSecurity::sl_g_loadfile(lua_State *L) ScriptApiBase *script = (ScriptApiBase *) lua_touserdata(L, -1); lua_pop(L, 1); + // Client implementation if (script->getType() == ScriptingType::Client) { - std::string display_path = readParam<std::string>(L, 1); - const std::string *path = script->getClient()->getModFile(display_path); - if (!path) { - std::string error_msg = "Coudln't find script called:" + display_path; + std::string path = readParam<std::string>(L, 1); + const std::string *contents = script->getClient()->getModFile(path); + if (!contents) { + std::string error_msg = "Coudln't find script called: " + path; lua_pushnil(L); lua_pushstring(L, error_msg.c_str()); return 2; } - if (!safeLoadFile(L, path->c_str(), display_path.c_str())) { + + std::string chunk_name = "@" + path; + if (!safeLoadString(L, *contents, chunk_name.c_str())) { lua_pushnil(L); lua_insert(L, -2); return 2; @@ -666,6 +647,8 @@ int ScriptApiSecurity::sl_g_loadfile(lua_State *L) return 1; } #endif + + // Server implementation const char *path = NULL; if (lua_isstring(L, 1)) { path = lua_tostring(L, 1); @@ -694,15 +677,11 @@ int ScriptApiSecurity::sl_g_loadstring(lua_State *L) size_t size; const char *code = lua_tolstring(L, 1, &size); + std::string code_s(code, size); - if (size > 0 && code[0] == LUA_SIGNATURE[0]) { + if (!safeLoadString(L, code_s, chunk_name)) { lua_pushnil(L); - lua_pushliteral(L, "Bytecode prohibited when mod security is enabled."); - return 2; - } - if (luaL_loadbuffer(L, code, size, chunk_name)) { - lua_pushnil(L); - lua_insert(L, lua_gettop(L) - 1); + lua_insert(L, -2); return 2; } return 1; diff --git a/src/script/cpp_api/s_security.h b/src/script/cpp_api/s_security.h index c31aff26b..73e763548 100644 --- a/src/script/cpp_api/s_security.h +++ b/src/script/cpp_api/s_security.h @@ -50,6 +50,8 @@ public: void initializeSecurityClient(); // Checks if the Lua state has been secured static bool isSecure(lua_State *L); + // Loads a string as Lua code safely (doesn't allow bytecode). + static bool safeLoadString(lua_State *L, const std::string &code, const char *chunk_name); // Loads a file as Lua code safely (doesn't allow bytecode). static bool safeLoadFile(lua_State *L, const char *path, const char *display_name = NULL); // Checks if mods are allowed to read (and optionally write) to the path |