diff options
author | SmallJoker <SmallJoker@users.noreply.github.com> | 2018-09-14 20:29:21 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-14 20:29:21 +0200 |
commit | 220ec79e4a10ea553310b16eb07d0c7a03fedb78 (patch) | |
tree | 778d497359c8c9b7a3880936aea7dabee5d18f70 | |
parent | 81c06dea9b6b863e0c8f6a9c052a5cea3a130eab (diff) | |
download | minetest-220ec79e4a10ea553310b16eb07d0c7a03fedb78.tar.gz minetest-220ec79e4a10ea553310b16eb07d0c7a03fedb78.tar.bz2 minetest-220ec79e4a10ea553310b16eb07d0c7a03fedb78.zip |
Inv deSerialize(): Prevent infinite loop, error on failure (#7711)
Throws an error about potentially damaged player inventories but proceeds converting the rest of them
-rw-r--r-- | src/inventory.cpp | 41 | ||||
-rw-r--r-- | src/remoteplayer.cpp | 7 |
2 files changed, 31 insertions, 17 deletions
diff --git a/src/inventory.cpp b/src/inventory.cpp index fb2dd245f..3bc67da1b 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -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) diff --git a/src/remoteplayer.cpp b/src/remoteplayer.cpp index e7c2462b6..3a72106de 100644 --- a/src/remoteplayer.cpp +++ b/src/remoteplayer.cpp @@ -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 |