Inv deSerialize(): Prevent infinite loop, error on failure (#7711)

Throws an error about potentially damaged player inventories but proceeds converting the rest of them
This commit is contained in:
SmallJoker 2018-09-14 20:29:21 +02:00 committed by GitHub
parent 81c06dea9b
commit 220ec79e4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 17 deletions

View File

@ -436,8 +436,7 @@ void InventoryList::deSerialize(std::istream &is)
u32 item_i = 0; u32 item_i = 0;
m_width = 0; m_width = 0;
for(;;) while (is.good()) {
{
std::string line; std::string line;
std::getline(is, line, '\n'); std::getline(is, line, '\n');
@ -447,14 +446,12 @@ void InventoryList::deSerialize(std::istream &is)
std::string name; std::string name;
std::getline(iss, name, ' '); std::getline(iss, name, ' ');
if (name == "EndInventoryList") { if (name == "EndInventoryList")
break; return;
}
// This is a temporary backwards compatibility fix // This is a temporary backwards compatibility fix
if (name == "end") { if (name == "end")
break; return;
}
if (name == "Width") { if (name == "Width") {
iss >> m_width; iss >> m_width;
@ -476,6 +473,14 @@ void InventoryList::deSerialize(std::istream &is)
m_items[item_i++].clear(); 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) InventoryList::InventoryList(const InventoryList &other)
@ -859,8 +864,7 @@ void Inventory::deSerialize(std::istream &is)
{ {
clear(); clear();
for(;;) while (is.good()) {
{
std::string line; std::string line;
std::getline(is, line, '\n'); std::getline(is, line, '\n');
@ -869,14 +873,12 @@ void Inventory::deSerialize(std::istream &is)
std::string name; std::string name;
std::getline(iss, name, ' '); std::getline(iss, name, ' ');
if (name == "EndInventory") { if (name == "EndInventory")
break; return;
}
// This is a temporary backwards compatibility fix // This is a temporary backwards compatibility fix
if (name == "end") { if (name == "end")
break; return;
}
if (name == "List") { if (name == "List") {
std::string listname; std::string listname;
@ -895,6 +897,13 @@ void Inventory::deSerialize(std::istream &is)
throw SerializationError("invalid inventory specifier: " + name); 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) InventoryList * Inventory::addList(const std::string &name, u32 size)

View File

@ -139,7 +139,12 @@ void RemotePlayer::deSerialize(std::istream &is, const std::string &playername,
} catch (SettingNotFoundException &e) {} } catch (SettingNotFoundException &e) {}
} }
try {
inventory.deSerialize(is); 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")) { if (!inventory.getList("craftpreview") && inventory.getList("craftresult")) {
// Convert players without craftpreview // Convert players without craftpreview