From 3adf6ef91cd8aa15f0cd62a421d6d16baf03d67d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20B=C3=A1lint=20Misius?= Date: Tue, 6 May 2025 21:31:55 +0200 Subject: [PATCH] Disallow particle lifetime management in some contexts Namely, in Create and ChangeType callbacks, which are themselves called by such lifetime management functions. Lifetime management includes explicit actions via partCreate and partKill, but also implicit ones such as changing the type property or changing x or y properties to values that move the particle beyond the edges and causes it to be killed. --- src/gui/game/GameControllerEvents.h | 1 + src/lua/LuaElements.cpp | 8 ++++++-- src/lua/LuaScriptInterface.cpp | 12 ++++++++++++ src/lua/LuaScriptInterface.h | 2 ++ src/lua/LuaSimulation.cpp | 12 ++++++------ 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/gui/game/GameControllerEvents.h b/src/gui/game/GameControllerEvents.h index 3d530f553..ed4ce1af0 100644 --- a/src/gui/game/GameControllerEvents.h +++ b/src/gui/game/GameControllerEvents.h @@ -13,6 +13,7 @@ enum EventTraits : uint32_t eventTraitInterfaceGraphics = UINT32_C(0x00000010), eventTraitConstSim = UINT32_C(0x00000020), eventTraitConstTools = UINT32_C(0x00000040), + eventTraitMonopartAccess = UINT32_C(0x00000080), }; constexpr EventTraits operator |(EventTraits lhs, EventTraits rhs) { diff --git a/src/lua/LuaElements.cpp b/src/lua/LuaElements.cpp index c0578ec03..e88f1cc61 100644 --- a/src/lua/LuaElements.cpp +++ b/src/lua/LuaElements.cpp @@ -225,11 +225,13 @@ static void luaCreateWrapper(ELEMENT_CREATE_FUNC_ARGS) lua_pushinteger(lsi->L, y); lua_pushinteger(lsi->L, t); lua_pushinteger(lsi->L, v); - if (tpt_lua_pcall(lsi->L, 5, 0, 0, eventTraitSimRng)) + lsi->monopartAccessPartID = i; + if (tpt_lua_pcall(lsi->L, 5, 0, 0, eventTraitSimRng | eventTraitMonopartAccess)) { lsi->Log(CommandInterface::LogError, "In create func: " + LuaGetError()); lua_pop(lsi->L, 1); } + lsi->monopartAccessPartID = -1; } } @@ -283,11 +285,13 @@ static void luaChangeTypeWrapper(ELEMENT_CHANGETYPE_FUNC_ARGS) lua_pushinteger(lsi->L, y); lua_pushinteger(lsi->L, from); lua_pushinteger(lsi->L, to); - if (tpt_lua_pcall(lsi->L, 5, 0, 0, eventTraitSimRng)) + lsi->monopartAccessPartID = i; + if (tpt_lua_pcall(lsi->L, 5, 0, 0, eventTraitSimRng | eventTraitMonopartAccess)) { lsi->Log(CommandInterface::LogError, "In change type: " + LuaGetError()); lua_pop(lsi->L, 1); } + lsi->monopartAccessPartID = -1; } } diff --git a/src/lua/LuaScriptInterface.cpp b/src/lua/LuaScriptInterface.cpp index d922c01bc..f71967940 100644 --- a/src/lua/LuaScriptInterface.cpp +++ b/src/lua/LuaScriptInterface.cpp @@ -319,10 +319,12 @@ void LuaSetParticleProperty(lua_State *L, int particleID, StructProperty propert auto *sim = lsi->sim; if (property.Name == "type") { + lsi->AssertMonopartAccessEvent(-1); sim->part_change_type(particleID, int(sim->parts[particleID].x+0.5f), int(sim->parts[particleID].y+0.5f), luaL_checkinteger(L, 3)); } else if (property.Name == "x" || property.Name == "y") { + lsi->AssertMonopartAccessEvent(-1); float val = luaL_checknumber(L, 3); float x = sim->parts[particleID].x; float y = sim->parts[particleID].y; @@ -332,6 +334,7 @@ void LuaSetParticleProperty(lua_State *L, int particleID, StructProperty propert } else { + lsi->AssertMonopartAccessEvent(particleID); LuaSetProperty(L, property, propertyAddress, 3); } } @@ -917,3 +920,12 @@ void LuaScriptInterface::AssertMutableToolsEvent() luaL_error(L, "this functionality is restricted to mutable tool events"); } } + +void LuaScriptInterface::AssertMonopartAccessEvent(int partID) +{ + AssertMutableSimEvent(); + if ((eventTraits & eventTraitMonopartAccess) && monopartAccessPartID != partID) + { + luaL_error(L, "particle management is restricted to ID %i", monopartAccessPartID); + } +} diff --git a/src/lua/LuaScriptInterface.h b/src/lua/LuaScriptInterface.h index ce11bcb1e..9572f7bc2 100644 --- a/src/lua/LuaScriptInterface.h +++ b/src/lua/LuaScriptInterface.h @@ -129,6 +129,7 @@ public: int textInputRefcount = 0; long unsigned int luaExecutionStart = 0; + int monopartAccessPartID = -1; private: std::vector> gameControllerEventHandlers; // must come after luaState @@ -154,6 +155,7 @@ public: void AssertInterfaceEvent(); void AssertMutableSimEvent(); void AssertMutableToolsEvent(); + void AssertMonopartAccessEvent(int partID); friend class CommandInterface; }; diff --git a/src/lua/LuaSimulation.cpp b/src/lua/LuaSimulation.cpp index 9e6ac76b9..6293a4002 100644 --- a/src/lua/LuaSimulation.cpp +++ b/src/lua/LuaSimulation.cpp @@ -312,7 +312,7 @@ static int partNeighbors(lua_State *L) static int partChangeType(lua_State *L) { auto *lsi = GetLSI(); - lsi->AssertMutableSimEvent(); + lsi->AssertMonopartAccessEvent(-1); int partIndex = lua_tointeger(L, 1); if(partIndex < 0 || partIndex >= NPART || !lsi->sim->parts[partIndex].type) return 0; @@ -323,7 +323,7 @@ static int partChangeType(lua_State *L) static int partCreate(lua_State *L) { auto *lsi = GetLSI(); - lsi->AssertMutableSimEvent(); + lsi->AssertMonopartAccessEvent(-1); int newID = lua_tointeger(L, 1); if (newID >= NPART || newID < -3) { @@ -386,6 +386,7 @@ static int partPosition(lua_State *L) { if(argCount == 1) { + lsi->AssertMonopartAccessEvent(-1); lua_pushnil(L); lua_pushnil(L); return 2; @@ -396,7 +397,7 @@ static int partPosition(lua_State *L) if (argCount == 3) { - lsi->AssertMutableSimEvent(); + lsi->AssertMonopartAccessEvent(-1); float x = sim->parts[particleID].x; float y = sim->parts[particleID].y; sim->move(particleID, (int)(x + 0.5f), (int)(y + 0.5f), lua_tonumber(L, 2), lua_tonumber(L, 3)); @@ -422,7 +423,7 @@ static int partProperty(lua_State *L) { if (argCount == 3) { - lsi->AssertMutableSimEvent(); + lsi->AssertMonopartAccessEvent(-1); return 0; } lua_pushnil(L); @@ -466,7 +467,6 @@ static int partProperty(lua_State *L) if (argCount == 3) { - lsi->AssertMutableSimEvent(); LuaSetParticleProperty(L, particleID, *prop, propertyAddress, 3); return 0; } @@ -477,7 +477,7 @@ static int partProperty(lua_State *L) static int partKill(lua_State *L) { auto *lsi = GetLSI(); - lsi->AssertMutableSimEvent(); + lsi->AssertMonopartAccessEvent(-1); if(lua_gettop(L)==2) lsi->sim->delete_part(lua_tointeger(L, 1), lua_tointeger(L, 2)); else