Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate player/item names coming from save file #7779

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions Source/items.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -645,8 +645,8 @@ void GetBookSpell(Item &item, int lvl)
const std::string_view spellName = GetSpellData(bs).sNameText;
const size_t iNameLen = std::string_view(item._iName).size();
const size_t iINameLen = std::string_view(item._iIName).size();
CopyUtf8(item._iName + iNameLen, spellName, sizeof(item._iName) - iNameLen);
CopyUtf8(item._iIName + iINameLen, spellName, sizeof(item._iIName) - iINameLen);
CopyUtf8(item._iName + iNameLen, spellName, ItemNameLength - iNameLen);
CopyUtf8(item._iIName + iINameLen, spellName, ItemNameLength - iINameLen);
item._iSpell = bs;
const SpellData &spellData = GetSpellData(bs);
item._iMinMag = spellData.minInt;
Expand Down Expand Up @@ -1134,12 +1134,12 @@ void GetStaffPower(const Player &player, Item &item, int lvl, SpellID bs, bool o
const ItemData &baseItemData = AllItemsList[item.IDidx];
std::string staffName = GenerateStaffName(baseItemData, item._iSpell, false);

CopyUtf8(item._iName, staffName, sizeof(item._iName));
CopyUtf8(item._iName, staffName, ItemNameLength);
if (preidx != -1) {
std::string staffNameMagical = GenerateStaffNameMagical(baseItemData, item._iSpell, preidx, false, std::nullopt);
CopyUtf8(item._iIName, staffNameMagical, sizeof(item._iIName));
CopyUtf8(item._iIName, staffNameMagical, ItemNameLength);
} else {
CopyUtf8(item._iIName, item._iName, sizeof(item._iIName));
CopyUtf8(item._iIName, item._iName, ItemNameLength);
}

CalcItemValue(item);
Expand Down Expand Up @@ -1242,9 +1242,9 @@ void GetItemPower(const Player &player, Item &item, int minlvl, int maxlvl, Affi
pSufix = &suffix;
});

CopyUtf8(item._iIName, GenerateMagicItemName(item._iName, pPrefix, pSufix, false), sizeof(item._iIName));
CopyUtf8(item._iIName, GenerateMagicItemName(item._iName, pPrefix, pSufix, false), ItemNameLength);
if (!StringInPanel(item._iIName)) {
CopyUtf8(item._iIName, GenerateMagicItemName(AllItemsList[item.IDidx].iSName, pPrefix, pSufix, false), sizeof(item._iIName));
CopyUtf8(item._iIName, GenerateMagicItemName(AllItemsList[item.IDidx].iSName, pPrefix, pSufix, false), ItemNameLength);
}
if (pPrefix != nullptr || pSufix != nullptr)
CalcItemValue(item);
Expand Down Expand Up @@ -1316,8 +1316,8 @@ void GetOilType(Item &item, int maxLvl)

int8_t t = rnd[GenerateRnd(cnt)];

CopyUtf8(item._iName, OilNames[t], sizeof(item._iName));
CopyUtf8(item._iIName, OilNames[t], sizeof(item._iIName));
CopyUtf8(item._iName, OilNames[t], ItemNameLength);
CopyUtf8(item._iIName, OilNames[t], ItemNameLength);
item._iMiscId = OilMagic[t];
item._ivalue = OilValues[t];
item._iIvalue = OilValues[t];
Expand Down Expand Up @@ -1479,7 +1479,7 @@ void GetUniqueItem(const Player &player, Item &item, _unique_items uid)
SaveItemPower(player, item, power);
}

CopyUtf8(item._iIName, uniqueItemData.UIName, sizeof(item._iIName));
CopyUtf8(item._iIName, uniqueItemData.UIName, ItemNameLength);
if (uniqueItemData.UICurs != ICURS_DEFAULT)
item._iCurs = uniqueItemData.UICurs;
item._iIvalue = uniqueItemData.UIValue;
Expand Down Expand Up @@ -2929,8 +2929,8 @@ void InitializeItem(Item &item, _item_indexes itemData)

item._itype = pAllItem.itype;
item._iCurs = pAllItem.iCurs;
CopyUtf8(item._iName, pAllItem.iName, sizeof(item._iName));
CopyUtf8(item._iIName, pAllItem.iName, sizeof(item._iIName));
CopyUtf8(item._iName, pAllItem.iName, ItemNameLength);
CopyUtf8(item._iIName, pAllItem.iName, ItemNameLength);
item._iLoc = pAllItem.iLoc;
item._iClass = pAllItem.iClass;
item._iMinDam = pAllItem.iMinDam;
Expand Down Expand Up @@ -3126,8 +3126,8 @@ void GetItemAttrs(Item &item, _item_indexes itemData, int lvl)
auto &baseItemData = AllItemsList[static_cast<size_t>(itemData)];
item._itype = baseItemData.itype;
item._iCurs = baseItemData.iCurs;
CopyUtf8(item._iName, baseItemData.iName, sizeof(item._iName));
CopyUtf8(item._iIName, baseItemData.iName, sizeof(item._iIName));
CopyUtf8(item._iName, baseItemData.iName, ItemNameLength);
CopyUtf8(item._iIName, baseItemData.iName, ItemNameLength);
item._iLoc = baseItemData.iLoc;
item._iClass = baseItemData.iClass;
item._iMinDam = baseItemData.iMinDam;
Expand Down Expand Up @@ -3570,8 +3570,8 @@ void RecreateEar(Item &item, uint16_t ic, uint32_t iseed, uint8_t bCursval, std:

std::string itemName = fmt::format(fmt::runtime("Ear of {:s}"), heroName);

CopyUtf8(item._iName, itemName, sizeof(item._iName));
CopyUtf8(item._iIName, heroName, sizeof(item._iIName));
CopyUtf8(item._iName, itemName, ItemNameLength);
CopyUtf8(item._iIName, heroName, ItemNameLength);

item._iCurs = ((bCursval >> 6) & 3) + ICURS_EAR_SORCERER;
item._ivalue = bCursval & 0x3F;
Expand Down
5 changes: 3 additions & 2 deletions Source/items.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ namespace devilution {
// Item indestructible durability
#define DUR_INDESTRUCTIBLE 255

constexpr int ItemNameLength = 64;
constexpr int MaxVendorValue = 140000;
constexpr int MaxVendorValueHf = 200000;
constexpr int MaxBoyValue = 90000;
Expand Down Expand Up @@ -200,8 +201,8 @@ struct Item {
bool _iPostDraw = false;
bool _iIdentified = false;
item_quality _iMagical = ITEM_QUALITY_NORMAL;
char _iName[64] = {};
char _iIName[64] = {};
char _iName[ItemNameLength] = {};
char _iIName[ItemNameLength] = {};
item_equip_type _iLoc = ILOC_NONE;
item_class _iClass = ICLASS_NONE;
uint8_t _iCurs = 0;
Expand Down
19 changes: 15 additions & 4 deletions Source/loadsave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ T SwapBE(T in)
}
}

void TerminateUtf8(char *str, size_t maxLength)
{
std::string_view inStr { str, maxLength };
std::string_view truncStr = TruncateUtf8(inStr, maxLength - 1);
size_t utf8Length = truncStr.size();
str[utf8Length] = '\0';
}

class LoadHelper {
std::unique_ptr<std::byte[]> m_buffer_;
size_t m_cur_ = 0;
Expand Down Expand Up @@ -268,8 +276,10 @@ void LoadItemData(LoadHelper &file, Item &item)
item._iPostDraw = file.NextBool32();
item._iIdentified = file.NextBool32();
item._iMagical = static_cast<item_quality>(file.NextLE<int8_t>());
file.NextBytes(item._iName, 64);
file.NextBytes(item._iIName, 64);
file.NextBytes(item._iName, ItemNameLength);
TerminateUtf8(item._iName, ItemNameLength);
file.NextBytes(item._iIName, ItemNameLength);
TerminateUtf8(item._iIName, ItemNameLength);
item._iLoc = static_cast<item_equip_type>(file.NextLE<int8_t>());
item._iClass = static_cast<item_class>(file.NextLE<uint8_t>());
file.Skip(1); // Alignment
Expand Down Expand Up @@ -439,6 +449,7 @@ void LoadPlayer(LoadHelper &file, Player &player)
player._pLvlChanging = file.NextBool8();

file.NextBytes(player._pName, PlayerNameLength);
TerminateUtf8(player._pName, PlayerNameLength);
player._pClass = static_cast<HeroClass>(file.NextLE<int8_t>());
file.Skip(3); // Alignment
player._pStrength = file.NextLE<int32_t>();
Expand Down Expand Up @@ -1088,8 +1099,8 @@ void SaveItem(SaveHelper &file, const Item &item)
file.WriteLE<uint32_t>(item._iPostDraw ? 1 : 0);
file.WriteLE<uint32_t>(item._iIdentified ? 1 : 0);
file.WriteLE<int8_t>(item._iMagical);
file.WriteBytes(item._iName, 64);
file.WriteBytes(item._iIName, 64);
file.WriteBytes(item._iName, ItemNameLength);
file.WriteBytes(item._iIName, ItemNameLength);
file.WriteLE<int8_t>(item._iLoc);
file.WriteLE<uint8_t>(item._iClass);
file.Skip(1); // Alignment
Expand Down
2 changes: 1 addition & 1 deletion Source/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2678,7 +2678,7 @@ StartPlayerKill(Player &player, DeathReason deathReason)
Item ear;
InitializeItem(ear, IDI_EAR);
CopyUtf8(ear._iName, fmt::format(fmt::runtime("Ear of {:s}"), player._pName), sizeof(ear._iName));
CopyUtf8(ear._iIName, player._pName, sizeof(ear._iIName));
CopyUtf8(ear._iIName, player._pName, ItemNameLength);
switch (player._pClass) {
case HeroClass::Sorcerer:
ear._iCurs = ICURS_EAR_SORCERER;
Expand Down
2 changes: 1 addition & 1 deletion test/pack_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ void ComparePackedItems(const ItemPack &item1LE, const ItemPack &item2LE)
}
}
typedef struct TestItemStruct {
char _iIName[64];
char _iIName[ItemNameLength];
ItemType _itype;
int _iClass;
int _iCurs;
Expand Down
Loading