Skip to content
Permalink
Browse files

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

Throws an error about potentially damaged player inventories but proceeds converting the rest of them
  • Loading branch information
SmallJoker committed Sep 14, 2018
1 parent 81c06de commit 220ec79e4a10ea553310b16eb07d0c7a03fedb78
Showing with 31 additions and 17 deletions.
  1. +25 −16 src/inventory.cpp
  2. +6 −1 src/remoteplayer.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)
@@ -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

0 comments on commit 220ec79

Please sign in to comment.