]> git.lizzy.rs Git - minetest.git/commitdiff
Inv deSerialize(): Prevent infinite loop, error on failure (#7711)
authorSmallJoker <SmallJoker@users.noreply.github.com>
Fri, 14 Sep 2018 18:29:21 +0000 (20:29 +0200)
committerGitHub <noreply@github.com>
Fri, 14 Sep 2018 18:29:21 +0000 (20:29 +0200)
Throws an error about potentially damaged player inventories but proceeds converting the rest of them

src/inventory.cpp
src/remoteplayer.cpp

index fb2dd245f396039f0c29ad818328dabbd8289c56..3bc67da1bc1e9279a7d520a4b853b01dea02795d 100644 (file)
@@ -436,8 +436,7 @@ void InventoryList::deSerialize(std::istream &is)
        u32 item_i = 0;
        m_width = 0;
 
-       for(;;)
-       {
+       while (is.good()) {
                std::string line;
                std::getline(is, line, '\n');
 
@@ -447,14 +446,12 @@ void InventoryList::deSerialize(std::istream &is)
                std::string name;
                std::getline(iss, name, ' ');
 
-               if (name == "EndInventoryList") {
-                       break;
-               }
+               if (name == "EndInventoryList")
+                       return;
 
                // This is a temporary backwards compatibility fix
-               if (name == "end") {
-                       break;
-               }
+               if (name == "end")
+                       return;
 
                if (name == "Width") {
                        iss >> m_width;
@@ -476,6 +473,14 @@ void InventoryList::deSerialize(std::istream &is)
                        m_items[item_i++].clear();
                }
        }
+
+       // Contents given to deSerialize() were not terminated properly: throw error.
+
+       std::ostringstream ss;
+       ss << "Malformatted inventory list. list="
+               << m_name << ", read " << item_i << " of " << getSize()
+               << " ItemStacks." << std::endl;
+       throw SerializationError(ss.str());
 }
 
 InventoryList::InventoryList(const InventoryList &other)
@@ -859,8 +864,7 @@ void Inventory::deSerialize(std::istream &is)
 {
        clear();
 
-       for(;;)
-       {
+       while (is.good()) {
                std::string line;
                std::getline(is, line, '\n');
 
@@ -869,14 +873,12 @@ void Inventory::deSerialize(std::istream &is)
                std::string name;
                std::getline(iss, name, ' ');
 
-               if (name == "EndInventory") {
-                       break;
-               }
+               if (name == "EndInventory")
+                       return;
 
                // This is a temporary backwards compatibility fix
-               if (name == "end") {
-                       break;
-               }
+               if (name == "end")
+                       return;
 
                if (name == "List") {
                        std::string listname;
@@ -895,6 +897,13 @@ void Inventory::deSerialize(std::istream &is)
                        throw SerializationError("invalid inventory specifier: " + name);
                }
        }
+
+       // Contents given to deSerialize() were not terminated properly: throw error.
+
+       std::ostringstream ss;
+       ss << "Malformatted inventory (damaged?). "
+               << m_lists.size() << " lists read." << std::endl;
+       throw SerializationError(ss.str());
 }
 
 InventoryList * Inventory::addList(const std::string &name, u32 size)
index e7c2462b625dc734cfb933c064c508f6eef5d8b1..3a72106de9ac2b1be8b6940f8563761b983bcbba 100644 (file)
@@ -139,7 +139,12 @@ void RemotePlayer::deSerialize(std::istream &is, const std::string &playername,
                } catch (SettingNotFoundException &e) {}
        }
 
-       inventory.deSerialize(is);
+       try {
+               inventory.deSerialize(is);
+       } catch (SerializationError &e) {
+               errorstream << "Failed to deserialize player inventory. player_name="
+                       << name << " " << e.what() << std::endl;
+       }
 
        if (!inventory.getList("craftpreview") && inventory.getList("craftresult")) {
                // Convert players without craftpreview