aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSmallJoker <SmallJoker@users.noreply.github.com>2018-09-14 20:29:21 +0200
committerGitHub <noreply@github.com>2018-09-14 20:29:21 +0200
commit220ec79e4a10ea553310b16eb07d0c7a03fedb78 (patch)
tree778d497359c8c9b7a3880936aea7dabee5d18f70
parent81c06dea9b6b863e0c8f6a9c052a5cea3a130eab (diff)
downloadminetest-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.cpp41
-rw-r--r--src/remoteplayer.cpp7
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