mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
InventoryManager: Disallow resizing or deleting inventory lists that are in use (#13360)
Naive solution to prevent InventoryList UAF and OOB ItemStack access caused by shrink/clear operations on InventoryLists within callbacks of an inventory action. Co-authored-by: Desour <ds.desour@proton.me>
This commit is contained in:
parent
4158b72971
commit
0fb6dbab36
3 changed files with 54 additions and 0 deletions
|
@ -452,6 +452,9 @@ void InventoryList::setSize(u32 newsize)
|
|||
if (newsize == m_items.size())
|
||||
return;
|
||||
|
||||
if (newsize < m_items.size())
|
||||
checkResizeLock();
|
||||
|
||||
m_items.resize(newsize);
|
||||
m_size = newsize;
|
||||
setModified();
|
||||
|
@ -549,6 +552,8 @@ void InventoryList::deSerialize(std::istream &is)
|
|||
|
||||
InventoryList & InventoryList::operator = (const InventoryList &other)
|
||||
{
|
||||
checkResizeLock();
|
||||
|
||||
m_items = other.m_items;
|
||||
m_size = other.m_size;
|
||||
m_width = other.m_width;
|
||||
|
@ -796,6 +801,15 @@ u32 InventoryList::moveItem(u32 i, InventoryList *dest, u32 dest_i,
|
|||
return (oldcount - item1.count);
|
||||
}
|
||||
|
||||
void InventoryList::checkResizeLock()
|
||||
{
|
||||
if (m_resize_locks == 0)
|
||||
return; // OK
|
||||
|
||||
throw BaseException("InventoryList '" + m_name
|
||||
+ "' is currently in use and cannot be deleted or resized.");
|
||||
}
|
||||
|
||||
/*
|
||||
Inventory
|
||||
*/
|
||||
|
@ -807,6 +821,12 @@ Inventory::~Inventory()
|
|||
|
||||
void Inventory::clear()
|
||||
{
|
||||
for (auto &m_list : m_lists) {
|
||||
// Placing this check within the destructor would be a logical solution
|
||||
// but that's generally a bad idea, thus manual calls beforehand:
|
||||
m_list->checkResizeLock();
|
||||
}
|
||||
|
||||
for (auto &m_list : m_lists) {
|
||||
delete m_list;
|
||||
}
|
||||
|
@ -948,7 +968,9 @@ InventoryList * Inventory::addList(const std::string &name, u32 size)
|
|||
// Remove existing lists
|
||||
s32 i = getListIndex(name);
|
||||
if (i != -1) {
|
||||
m_lists[i]->checkResizeLock();
|
||||
delete m_lists[i];
|
||||
|
||||
m_lists[i] = new InventoryList(name, size, m_itemdef);
|
||||
m_lists[i]->setModified();
|
||||
return m_lists[i];
|
||||
|
@ -978,6 +1000,8 @@ bool Inventory::deleteList(const std::string &name)
|
|||
if(i == -1)
|
||||
return false;
|
||||
|
||||
m_lists[i]->checkResizeLock();
|
||||
|
||||
setModified();
|
||||
delete m_lists[i];
|
||||
m_lists.erase(m_lists.begin() + i);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue