mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-28 12:40:06 +00:00
Fix use after move in InfoOrder::insertInfo
When it->second.mPosition->mPrev != value.mPrev value is first moved into *mPosition and then used to get mPrev. Since mPrev is RefId and it's copy-only type there is no real problem but coverity complains about it. Also enforce contract of insertInfo to support move-only types by adding a test for a value type with deleted copy constructors.
This commit is contained in:
parent
d2f16774d9
commit
66c5944ecf
@ -89,6 +89,7 @@ file(GLOB UNITTEST_SRC_FILES
|
|||||||
esm3/readerscache.cpp
|
esm3/readerscache.cpp
|
||||||
esm3/testsaveload.cpp
|
esm3/testsaveload.cpp
|
||||||
esm3/testesmwriter.cpp
|
esm3/testesmwriter.cpp
|
||||||
|
esm3/testinfoorder.cpp
|
||||||
|
|
||||||
nifosg/testnifloader.cpp
|
nifosg/testnifloader.cpp
|
||||||
)
|
)
|
||||||
|
27
apps/openmw_test_suite/esm3/testinfoorder.cpp
Normal file
27
apps/openmw_test_suite/esm3/testinfoorder.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include <components/esm3/infoorder.hpp>
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct Value
|
||||||
|
{
|
||||||
|
RefId mId;
|
||||||
|
RefId mPrev;
|
||||||
|
|
||||||
|
Value() = default;
|
||||||
|
Value(const Value&) = delete;
|
||||||
|
Value(Value&&) = default;
|
||||||
|
Value& operator=(const Value&) = delete;
|
||||||
|
Value& operator=(Value&&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(Esm3InfoOrderTest, insertInfoShouldNotCopyValue)
|
||||||
|
{
|
||||||
|
InfoOrder<Value> order;
|
||||||
|
order.insertInfo(Value{}, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -24,19 +24,12 @@ namespace ESM
|
|||||||
|
|
||||||
auto it = mInfoPositions.find(value.mId);
|
auto it = mInfoPositions.find(value.mId);
|
||||||
|
|
||||||
if (it != mInfoPositions.end())
|
if (it != mInfoPositions.end() && it->second.mPosition->mPrev == value.mPrev)
|
||||||
{
|
{
|
||||||
bool samePrev = it->second.mPosition->mPrev == value.mPrev;
|
|
||||||
*it->second.mPosition = std::forward<V>(value);
|
*it->second.mPosition = std::forward<V>(value);
|
||||||
it->second.mDeleted = deleted;
|
it->second.mDeleted = deleted;
|
||||||
if (samePrev)
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
it = mInfoPositions.emplace(value.mId, Item{ .mPosition = mOrderedInfo.end(), .mDeleted = deleted })
|
|
||||||
.first;
|
|
||||||
|
|
||||||
Item& item = it->second;
|
|
||||||
|
|
||||||
auto before = mOrderedInfo.begin();
|
auto before = mOrderedInfo.begin();
|
||||||
if (!value.mPrev.empty())
|
if (!value.mPrev.empty())
|
||||||
@ -47,10 +40,22 @@ namespace ESM
|
|||||||
else
|
else
|
||||||
before = mOrderedInfo.end();
|
before = mOrderedInfo.end();
|
||||||
}
|
}
|
||||||
if (item.mPosition == mOrderedInfo.end())
|
|
||||||
item.mPosition = mOrderedInfo.insert(before, std::forward<V>(value));
|
if (it == mInfoPositions.end())
|
||||||
|
{
|
||||||
|
const RefId id = value.mId;
|
||||||
|
mInfoPositions.emplace(id,
|
||||||
|
Item{
|
||||||
|
.mPosition = mOrderedInfo.insert(before, std::forward<V>(value)),
|
||||||
|
.mDeleted = deleted,
|
||||||
|
});
|
||||||
|
}
|
||||||
else
|
else
|
||||||
mOrderedInfo.splice(before, mOrderedInfo, item.mPosition);
|
{
|
||||||
|
*it->second.mPosition = std::forward<V>(value);
|
||||||
|
it->second.mDeleted = deleted;
|
||||||
|
mOrderedInfo.splice(before, mOrderedInfo, it->second.mPosition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeInfo(const RefId& infoRefId)
|
void removeInfo(const RefId& infoRefId)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user