From 942891787028d0cbce226c2af0536a18d5a37df2 Mon Sep 17 00:00:00 2001 From: savilli <78875209+savilli@users.noreply.github.com> Date: Fri, 16 Sep 2022 13:20:14 +0200 Subject: [PATCH] Fix UAF in craft recipes (#12763) If you call minetest.clear_craft after minetest.register_alias_force, the craft definition reference may not be removed from m_output_craft_definitions leading to UAF. --- src/craftdef.cpp | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/craftdef.cpp b/src/craftdef.cpp index c05a0cfb7..053e73bea 100644 --- a/src/craftdef.cpp +++ b/src/craftdef.cpp @@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes.h" #include "log.h" #include -#include +#include #include #include "gamedef.h" #include "inventory.h" @@ -1026,26 +1026,31 @@ public: // Recipes are not yet hashed at this point std::vector &defs = m_craft_defs[(int)CRAFT_HASH_TYPE_UNHASHED][0]; + std::unordered_set defs_to_remove; std::vector new_defs; - bool got_hit = false; + for (auto def : defs) { - if (!def->check(input, gamedef)) { + if (def->check(input, gamedef)) + defs_to_remove.insert(def); + else new_defs.push_back(def); - continue; - } - got_hit = true; - std::string output = def->getOutput(input, gamedef).item; - delete def; - auto it = m_output_craft_definitions.find(craftGetItemName(output, gamedef)); - if (it == m_output_craft_definitions.end()) - continue; - std::vector &outdefs = it->second; - outdefs.erase(std::remove(outdefs.begin(), outdefs.end(), def), outdefs.end()); } - if (got_hit) + + if (!defs_to_remove.empty()) { + for (auto def : defs_to_remove) + delete def; + defs.swap(new_defs); - return got_hit; + for (auto &output : m_output_craft_definitions) { + std::vector &outdefs = output.second; + outdefs.erase(std::remove_if(outdefs.begin(), outdefs.end(), [&](const CraftDefinition* def) { + return defs_to_remove.find(def) != defs_to_remove.end(); + }), outdefs.end()); + } + } + + return !defs_to_remove.empty(); } virtual std::string dump() const