diff options
author | SmallJoker <SmallJoker@users.noreply.github.com> | 2021-05-29 11:44:48 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-29 11:44:48 +0200 |
commit | 5bf72468f3a0925a9fc3c9acacf3f6e138bff35e (patch) | |
tree | f4176ee197cf895c881c14d2162d3df6e5629577 | |
parent | ff48619a857da2158768314f08191994b33ffee9 (diff) | |
download | minetest-5bf72468f3a0925a9fc3c9acacf3f6e138bff35e.tar.gz minetest-5bf72468f3a0925a9fc3c9acacf3f6e138bff35e.tar.bz2 minetest-5bf72468f3a0925a9fc3c9acacf3f6e138bff35e.zip |
UnitSAO: Prevent circular attachments
-rw-r--r-- | doc/lua_api.txt | 2 | ||||
-rw-r--r-- | src/server/unit_sao.cpp | 13 |
2 files changed, 15 insertions, 0 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt index ef86efcc1..6c7ae0fb5 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6314,6 +6314,8 @@ object you are working with still exists. Default `{x=0, y=0, z=0}` * `forced_visible`: Boolean to control whether the attached entity should appear in first person. Default `false`. + * This command may fail silently (do nothing) when it would result + in circular attachments. * `get_attach()`: returns parent, bone, position, rotation, forced_visible, or nil if it isn't attached. * `get_children()`: returns a list of ObjectRefs that are attached to the diff --git a/src/server/unit_sao.cpp b/src/server/unit_sao.cpp index fa6c8f0f4..acbdd478a 100644 --- a/src/server/unit_sao.cpp +++ b/src/server/unit_sao.cpp @@ -124,6 +124,19 @@ void UnitSAO::sendOutdatedData() void UnitSAO::setAttachment(int parent_id, const std::string &bone, v3f position, v3f rotation, bool force_visible) { + auto *obj = parent_id ? m_env->getActiveObject(parent_id) : nullptr; + if (obj) { + // Do checks to avoid circular references + // The chain of wanted parent must not refer or contain "this" + for (obj = obj->getParent(); obj; obj = obj->getParent()) { + if (obj == this) { + warningstream << "Mod bug: Attempted to attach object " << m_id << " to parent " + << parent_id << " but former is an (in)direct parent of latter." << std::endl; + return; + } + } + } + // Attachments need to be handled on both the server and client. // If we just attach on the server, we can only copy the position of the parent. // Attachments are still sent to clients at an interval so players might see them |