Skip to content

Commit 220ec79

Browse files
authoredSep 14, 2018
Inv deSerialize(): Prevent infinite loop, error on failure (#7711)
Throws an error about potentially damaged player inventories but proceeds converting the rest of them
1 parent 81c06de commit 220ec79

File tree

2 files changed

+31
-17
lines changed

2 files changed

+31
-17
lines changed
 

‎src/inventory.cpp

+25-16
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,7 @@ void InventoryList::deSerialize(std::istream &is)
436436
u32 item_i = 0;
437437
m_width = 0;
438438

439-
for(;;)
440-
{
439+
while (is.good()) {
441440
std::string line;
442441
std::getline(is, line, '\n');
443442

@@ -447,14 +446,12 @@ void InventoryList::deSerialize(std::istream &is)
447446
std::string name;
448447
std::getline(iss, name, ' ');
449448

450-
if (name == "EndInventoryList") {
451-
break;
452-
}
449+
if (name == "EndInventoryList")
450+
return;
453451

454452
// This is a temporary backwards compatibility fix
455-
if (name == "end") {
456-
break;
457-
}
453+
if (name == "end")
454+
return;
458455

459456
if (name == "Width") {
460457
iss >> m_width;
@@ -476,6 +473,14 @@ void InventoryList::deSerialize(std::istream &is)
476473
m_items[item_i++].clear();
477474
}
478475
}
476+
477+
// Contents given to deSerialize() were not terminated properly: throw error.
478+
479+
std::ostringstream ss;
480+
ss << "Malformatted inventory list. list="
481+
<< m_name << ", read " << item_i << " of " << getSize()
482+
<< " ItemStacks." << std::endl;
483+
throw SerializationError(ss.str());
479484
}
480485

481486
InventoryList::InventoryList(const InventoryList &other)
@@ -859,8 +864,7 @@ void Inventory::deSerialize(std::istream &is)
859864
{
860865
clear();
861866

862-
for(;;)
863-
{
867+
while (is.good()) {
864868
std::string line;
865869
std::getline(is, line, '\n');
866870

@@ -869,14 +873,12 @@ void Inventory::deSerialize(std::istream &is)
869873
std::string name;
870874
std::getline(iss, name, ' ');
871875

872-
if (name == "EndInventory") {
873-
break;
874-
}
876+
if (name == "EndInventory")
877+
return;
875878

876879
// This is a temporary backwards compatibility fix
877-
if (name == "end") {
878-
break;
879-
}
880+
if (name == "end")
881+
return;
880882

881883
if (name == "List") {
882884
std::string listname;
@@ -895,6 +897,13 @@ void Inventory::deSerialize(std::istream &is)
895897
throw SerializationError("invalid inventory specifier: " + name);
896898
}
897899
}
900+
901+
// Contents given to deSerialize() were not terminated properly: throw error.
902+
903+
std::ostringstream ss;
904+
ss << "Malformatted inventory (damaged?). "
905+
<< m_lists.size() << " lists read." << std::endl;
906+
throw SerializationError(ss.str());
898907
}
899908

900909
InventoryList * Inventory::addList(const std::string &name, u32 size)

‎src/remoteplayer.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,12 @@ void RemotePlayer::deSerialize(std::istream &is, const std::string &playername,
139139
} catch (SettingNotFoundException &e) {}
140140
}
141141

142-
inventory.deSerialize(is);
142+
try {
143+
inventory.deSerialize(is);
144+
} catch (SerializationError &e) {
145+
errorstream << "Failed to deserialize player inventory. player_name="
146+
<< name << " " << e.what() << std::endl;
147+
}
143148

144149
if (!inventory.getList("craftpreview") && inventory.getList("craftresult")) {
145150
// Convert players without craftpreview

0 commit comments

Comments
 (0)
Please sign in to comment.