1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-28 08:37:12 +00:00

Fix heap use after free in components/lua/storage.cpp

This commit is contained in:
Petr Mikheev 2022-01-23 22:33:00 +01:00
parent c263bbf0f6
commit 067d71f7eb
3 changed files with 16 additions and 13 deletions

View File

@ -91,10 +91,10 @@ namespace
mLua.safe_script("permanent:set('z', 4)"); mLua.safe_script("permanent:set('z', 4)");
LuaUtil::LuaStorage storage2(mLua); LuaUtil::LuaStorage storage2(mLua);
storage2.load(tmpFile);
mLua["permanent"] = storage2.getMutableSection("permanent"); mLua["permanent"] = storage2.getMutableSection("permanent");
mLua["temporary"] = storage2.getMutableSection("temporary"); mLua["temporary"] = storage2.getMutableSection("temporary");
storage2.load(tmpFile);
EXPECT_EQ(get<int>(mLua, "permanent:get('x')"), 1); EXPECT_EQ(get<int>(mLua, "permanent:get('x')"), 1);
EXPECT_TRUE(get<bool>(mLua, "permanent:get('z') == nil")); EXPECT_TRUE(get<bool>(mLua, "permanent:get('z') == nil"));
EXPECT_TRUE(get<bool>(mLua, "temporary:get('y') == nil")); EXPECT_TRUE(get<bool>(mLua, "temporary:get('y') == nil"));

View File

@ -121,7 +121,10 @@ namespace LuaUtil
while (it != mData.end()) while (it != mData.end())
{ {
if (!it->second->mPermanent) if (!it->second->mPermanent)
{
it->second->mValues.clear();
it = mData.erase(it); it = mData.erase(it);
}
else else
++it; ++it;
} }
@ -129,7 +132,7 @@ namespace LuaUtil
void LuaStorage::load(const std::string& path) void LuaStorage::load(const std::string& path)
{ {
mData.clear(); assert(mData.empty()); // Shouldn't be used before loading
try try
{ {
Log(Debug::Info) << "Loading Lua storage \"" << path << "\" (" << std::filesystem::file_size(path) << " bytes)"; Log(Debug::Info) << "Loading Lua storage \"" << path << "\" (" << std::filesystem::file_size(path) << " bytes)";
@ -138,7 +141,7 @@ namespace LuaUtil
sol::table data = deserialize(mLua, serializedData); sol::table data = deserialize(mLua, serializedData);
for (const auto& [sectionName, sectionTable] : data) for (const auto& [sectionName, sectionTable] : data)
{ {
Section* section = getSection(sectionName.as<std::string_view>()); const std::shared_ptr<Section>& section = getSection(sectionName.as<std::string_view>());
for (const auto& [key, value] : sol::table(sectionTable)) for (const auto& [key, value] : sol::table(sectionTable))
section->set(key.as<std::string_view>(), value); section->set(key.as<std::string_view>(), value);
} }
@ -164,26 +167,26 @@ namespace LuaUtil
fout.close(); fout.close();
} }
LuaStorage::Section* LuaStorage::getSection(std::string_view sectionName) const std::shared_ptr<LuaStorage::Section>& LuaStorage::getSection(std::string_view sectionName)
{ {
auto it = mData.find(sectionName); auto it = mData.find(sectionName);
if (it != mData.end()) if (it != mData.end())
return it->second.get(); return it->second;
auto section = std::make_unique<Section>(this, std::string(sectionName)); auto section = std::make_shared<Section>(this, std::string(sectionName));
sectionName = section->mSectionName; sectionName = section->mSectionName;
auto [newIt, _] = mData.emplace(sectionName, std::move(section)); auto [newIt, _] = mData.emplace(sectionName, std::move(section));
return newIt->second.get(); return newIt->second;
} }
sol::object LuaStorage::getReadOnlySection(std::string_view sectionName) sol::object LuaStorage::getReadOnlySection(std::string_view sectionName)
{ {
Section* section = getSection(sectionName); const std::shared_ptr<Section>& section = getSection(sectionName);
return sol::make_object<SectionReadOnlyView>(mLua, SectionReadOnlyView{section, section->mChangeCounter}); return sol::make_object<SectionReadOnlyView>(mLua, SectionReadOnlyView{section, section->mChangeCounter});
} }
sol::object LuaStorage::getMutableSection(std::string_view sectionName) sol::object LuaStorage::getMutableSection(std::string_view sectionName)
{ {
Section* section = getSection(sectionName); const std::shared_ptr<Section>& section = getSection(sectionName);
return sol::make_object<SectionMutableView>(mLua, SectionMutableView{section, section->mChangeCounter}); return sol::make_object<SectionMutableView>(mLua, SectionMutableView{section, section->mChangeCounter});
} }

View File

@ -60,19 +60,19 @@ namespace LuaUtil
}; };
struct SectionMutableView struct SectionMutableView
{ {
Section* mSection = nullptr; std::shared_ptr<Section> mSection = nullptr;
int64_t mLastCheck = 0; int64_t mLastCheck = 0;
}; };
struct SectionReadOnlyView struct SectionReadOnlyView
{ {
Section* mSection = nullptr; std::shared_ptr<Section> mSection = nullptr;
int64_t mLastCheck = 0; int64_t mLastCheck = 0;
}; };
Section* getSection(std::string_view sectionName); const std::shared_ptr<Section>& getSection(std::string_view sectionName);
lua_State* mLua; lua_State* mLua;
std::map<std::string_view, std::unique_ptr<Section>> mData; std::map<std::string_view, std::shared_ptr<Section>> mData;
std::optional<ListenerFn> mListener; std::optional<ListenerFn> mListener;
}; };