Merge branch 'mainmembers' into 'master'
Some checks failed
Build and test / Ubuntu (push) Has been cancelled
Build and test / MacOS (push) Has been cancelled
Build and test / Read .env file and expose it as output (push) Has been cancelled
Build and test / Windows (2019) (push) Has been cancelled
Build and test / Windows (2022) (push) Has been cancelled

Fix more potential use-after-free issues

See merge request OpenMW/openmw!4566
This commit is contained in:
Alexei Kotov 2025-03-07 00:25:35 +03:00
commit 5f92d520ee
15 changed files with 52 additions and 43 deletions

View file

@ -71,7 +71,8 @@ namespace MWLua
{ {
SelfObject* obj = mObject.asSelfObject(); SelfObject* obj = mObject.asSelfObject();
addStatUpdateAction(context.mLuaManager, *obj); addStatUpdateAction(context.mLuaManager, *obj);
obj->mStatsCache[SelfObject::CachedStat{ &ItemData::setValue, std::monostate{}, prop }] = value; obj->mStatsCache[SelfObject::CachedStat{ &ItemData::setValue, std::monostate{}, prop }]
= sol::main_object(value);
} }
else else
throw std::runtime_error("Only global or self scripts can set the value"); throw std::runtime_error("Only global or self scripts can set the value");

View file

@ -54,7 +54,7 @@ namespace MWLua
{ {
} }
MWBase::LuaManager::ActorControls mControls; MWBase::LuaManager::ActorControls mControls;
std::map<CachedStat, sol::object> mStatsCache; std::map<CachedStat, sol::main_object> mStatsCache;
bool mIsActive; bool mIsActive;
}; };

View file

@ -123,7 +123,8 @@ namespace MWLua
SelfObject* obj = mObject.asSelfObject(); SelfObject* obj = mObject.asSelfObject();
addStatUpdateAction(context.mLuaManager, *obj); addStatUpdateAction(context.mLuaManager, *obj);
obj->mStatsCache[SelfObject::CachedStat{ &setNpcValue, attributeId, "skillIncreasesForAttribute" }] = value; obj->mStatsCache[SelfObject::CachedStat{ &setNpcValue, attributeId, "skillIncreasesForAttribute" }]
= sol::main_object(value);
} }
}; };
@ -159,7 +160,7 @@ namespace MWLua
SelfObject* obj = mObject.asSelfObject(); SelfObject* obj = mObject.asSelfObject();
addStatUpdateAction(context.mLuaManager, *obj); addStatUpdateAction(context.mLuaManager, *obj);
obj->mStatsCache[SelfObject::CachedStat{ &setNpcValue, specialization, "skillIncreasesForSpecialization" }] obj->mStatsCache[SelfObject::CachedStat{ &setNpcValue, specialization, "skillIncreasesForSpecialization" }]
= value; = sol::main_object(value);
} }
}; };
@ -183,7 +184,8 @@ namespace MWLua
{ {
SelfObject* obj = mObject.asSelfObject(); SelfObject* obj = mObject.asSelfObject();
addStatUpdateAction(context.mLuaManager, *obj); addStatUpdateAction(context.mLuaManager, *obj);
obj->mStatsCache[SelfObject::CachedStat{ &setCreatureValue, std::monostate{}, "current" }] = value; obj->mStatsCache[SelfObject::CachedStat{ &setCreatureValue, std::monostate{}, "current" }]
= sol::main_object(value);
} }
sol::object getProgress(const Context& context) const sol::object getProgress(const Context& context) const
@ -204,7 +206,8 @@ namespace MWLua
SelfObject* obj = mObject.asSelfObject(); SelfObject* obj = mObject.asSelfObject();
addStatUpdateAction(context.mLuaManager, *obj); addStatUpdateAction(context.mLuaManager, *obj);
obj->mStatsCache[SelfObject::CachedStat{ &setNpcValue, std::monostate{}, "progress" }] = value; obj->mStatsCache[SelfObject::CachedStat{ &setNpcValue, std::monostate{}, "progress" }]
= sol::main_object(value);
} }
SkillIncreasesForAttributeStats getSkillIncreasesForAttributeStats() const SkillIncreasesForAttributeStats getSkillIncreasesForAttributeStats() const
@ -258,7 +261,7 @@ namespace MWLua
{ {
SelfObject* obj = mObject.asSelfObject(); SelfObject* obj = mObject.asSelfObject();
addStatUpdateAction(context.mLuaManager, *obj); addStatUpdateAction(context.mLuaManager, *obj);
obj->mStatsCache[SelfObject::CachedStat{ &DynamicStat::setValue, mIndex, prop }] = value; obj->mStatsCache[SelfObject::CachedStat{ &DynamicStat::setValue, mIndex, prop }] = sol::main_object(value);
} }
static void setValue(Index i, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value) static void setValue(Index i, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value)
@ -318,7 +321,7 @@ namespace MWLua
{ {
SelfObject* obj = mObject.asSelfObject(); SelfObject* obj = mObject.asSelfObject();
addStatUpdateAction(context.mLuaManager, *obj); addStatUpdateAction(context.mLuaManager, *obj);
obj->mStatsCache[SelfObject::CachedStat{ &AttributeStat::setValue, mId, prop }] = value; obj->mStatsCache[SelfObject::CachedStat{ &AttributeStat::setValue, mId, prop }] = sol::main_object(value);
} }
static void setValue(Index i, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value) static void setValue(Index i, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value)
@ -402,7 +405,7 @@ namespace MWLua
{ {
SelfObject* obj = mObject.asSelfObject(); SelfObject* obj = mObject.asSelfObject();
addStatUpdateAction(context.mLuaManager, *obj); addStatUpdateAction(context.mLuaManager, *obj);
obj->mStatsCache[SelfObject::CachedStat{ &SkillStat::setValue, mId, prop }] = value; obj->mStatsCache[SelfObject::CachedStat{ &SkillStat::setValue, mId, prop }] = sol::main_object(value);
} }
static void setValue(Index index, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value) static void setValue(Index index, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value)
@ -465,7 +468,8 @@ namespace MWLua
{ {
SelfObject* obj = mObject.asSelfObject(); SelfObject* obj = mObject.asSelfObject();
addStatUpdateAction(context.mLuaManager, *obj); addStatUpdateAction(context.mLuaManager, *obj);
obj->mStatsCache[SelfObject::CachedStat{ &AIStat::setValue, static_cast<int>(mIndex), prop }] = value; obj->mStatsCache[SelfObject::CachedStat{ &AIStat::setValue, static_cast<int>(mIndex), prop }]
= sol::main_object(value);
} }
static void setValue(Index i, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value) static void setValue(Index i, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value)

View file

@ -168,7 +168,8 @@ namespace MWLua
if (index == LuaUi::Layer::count()) if (index == LuaUi::Layer::count())
throw std::logic_error(std::string("Layer not found")); throw std::logic_error(std::string("Layer not found"));
index++; index++;
context.mLuaManager->addAction([=]() { LuaUi::Layer::insert(index, name, options); }, "Insert UI layer"); context.mLuaManager->addAction(
[=, name = std::string(name)]() { LuaUi::Layer::insert(index, name, options); }, "Insert UI layer");
}; };
layersTable["insertBefore"] = [context]( layersTable["insertBefore"] = [context](
std::string_view beforename, std::string_view name, const sol::object& opt) { std::string_view beforename, std::string_view name, const sol::object& opt) {
@ -177,7 +178,8 @@ namespace MWLua
size_t index = LuaUi::Layer::indexOf(beforename); size_t index = LuaUi::Layer::indexOf(beforename);
if (index == LuaUi::Layer::count()) if (index == LuaUi::Layer::count())
throw std::logic_error(std::string("Layer not found")); throw std::logic_error(std::string("Layer not found"));
context.mLuaManager->addAction([=]() { LuaUi::Layer::insert(index, name, options); }, "Insert UI layer"); context.mLuaManager->addAction(
[=, name = std::string(name)]() { LuaUi::Layer::insert(index, name, options); }, "Insert UI layer");
}; };
sol::table layers = LuaUtil::makeReadOnly(layersTable); sol::table layers = LuaUtil::makeReadOnly(layersTable);
sol::table layersMeta = layers[sol::metatable_key]; sol::table layersMeta = layers[sol::metatable_key];
@ -285,8 +287,9 @@ namespace MWLua
return res; return res;
}; };
api["_setWindowDisabled"] api["_setWindowDisabled"]
= [windowManager, luaManager = context.mLuaManager](std::string_view window, bool disabled) { = [windowManager, luaManager = context.mLuaManager](std::string window, bool disabled) {
luaManager->addAction([=]() { windowManager->setDisabledByLua(window, disabled); }); luaManager->addAction(
[=, window = std::move(window)]() { windowManager->setDisabledByLua(window, disabled); });
}; };
// TODO // TODO
@ -308,7 +311,7 @@ namespace MWLua
return res.str(); return res.str();
}; };
element["layout"] = sol::property([](const LuaUi::Element& element) { return element.mLayout; }, element["layout"] = sol::property([](const LuaUi::Element& element) { return element.mLayout; },
[](LuaUi::Element& element, const sol::table& layout) { element.mLayout = layout; }); [](LuaUi::Element& element, const sol::main_table& layout) { element.mLayout = layout; });
element["update"] = [luaManager = context.mLuaManager](const std::shared_ptr<LuaUi::Element>& element) { element["update"] = [luaManager = context.mLuaManager](const std::shared_ptr<LuaUi::Element>& element) {
if (element->mState != LuaUi::Element::Created) if (element->mState != LuaUi::Element::Created)
return; return;

View file

@ -343,7 +343,8 @@ namespace LuaUtil
} }
sol::protected_function_result LuaState::runInNewSandbox(const VFS::Path::Normalized& path, sol::protected_function_result LuaState::runInNewSandbox(const VFS::Path::Normalized& path,
const std::string& envName, const std::map<std::string, sol::object>& packages, const sol::object& hiddenData) const std::string& envName, const std::map<std::string, sol::main_object>& packages,
const sol::main_object& hiddenData)
{ {
// TODO // TODO
sol::protected_function script = loadScriptAndCache(path); sol::protected_function script = loadScriptAndCache(path);

View file

@ -148,8 +148,8 @@ namespace LuaUtil
// should be either a sol::table or a sol::function. If it is a function, it will be evaluated // should be either a sol::table or a sol::function. If it is a function, it will be evaluated
// (once per sandbox) with the argument 'hiddenData' the first time when requested. // (once per sandbox) with the argument 'hiddenData' the first time when requested.
sol::protected_function_result runInNewSandbox(const VFS::Path::Normalized& path, sol::protected_function_result runInNewSandbox(const VFS::Path::Normalized& path,
const std::string& envName = "unnamed", const std::map<std::string, sol::object>& packages = {}, const std::string& envName = "unnamed", const std::map<std::string, sol::main_object>& packages = {},
const sol::object& hiddenData = sol::nil); const sol::main_object& hiddenData = sol::nil);
void dropScriptCache() { mCompiledScripts.clear(); } void dropScriptCache() { mCompiledScripts.clear(); }

View file

@ -52,7 +52,7 @@ namespace LuaUtil
Log(Debug::Error) << mNamePrefix << "[" << scriptPath(scriptId) << "] " << msg << ": " << e.what(); Log(Debug::Error) << mNamePrefix << "[" << scriptPath(scriptId) << "] " << msg << ": " << e.what();
} }
void ScriptsContainer::addPackage(std::string packageName, sol::object package) void ScriptsContainer::addPackage(std::string packageName, sol::main_object package)
{ {
if (!package.is<sol::userdata>()) if (!package.is<sol::userdata>())
throw std::logic_error("Expected package to be read-only: " + packageName); throw std::logic_error("Expected package to be read-only: " + packageName);
@ -312,7 +312,7 @@ namespace LuaUtil
{ {
if (next->mOnOverride) if (next->mOnOverride)
{ {
sol::object prevInterface = sol::nil; sol::main_object prevInterface = sol::nil;
if (prev) if (prev)
prevInterface = *prev->mInterface; prevInterface = *prev->mInterface;
try try

View file

@ -90,7 +90,7 @@ namespace LuaUtil
// Adds package that will be available (via `require`) for all scripts in the container. // Adds package that will be available (via `require`) for all scripts in the container.
// Automatically applies LuaUtil::makeReadOnly to the package. // Automatically applies LuaUtil::makeReadOnly to the package.
void addPackage(std::string packageName, sol::object package); void addPackage(std::string packageName, sol::main_object package);
// Gets script with given id from ScriptsConfiguration, finds the source in the virtual file system, starts as a // Gets script with given id from ScriptsConfiguration, finds the source in the virtual file system, starts as a
// new script, adds it to the container, and calls onInit for this script. Returns `true` if the script was // new script, adds it to the container, and calls onInit for this script. Returns `true` if the script was
@ -168,7 +168,7 @@ namespace LuaUtil
struct Handler struct Handler
{ {
int mScriptId; int mScriptId;
sol::function mFn; sol::main_function mFn;
}; };
struct EngineHandlerList struct EngineHandlerList
@ -212,11 +212,11 @@ namespace LuaUtil
private: private:
struct Script struct Script
{ {
std::optional<sol::function> mOnSave; std::optional<sol::main_function> mOnSave;
std::optional<sol::function> mOnOverride; std::optional<sol::main_function> mOnOverride;
std::optional<sol::table> mInterface; std::optional<sol::main_table> mInterface;
std::string mInterfaceName; std::string mInterfaceName;
sol::table mHiddenData; sol::main_table mHiddenData;
std::map<std::string, sol::main_protected_function> mRegisteredCallbacks; std::map<std::string, sol::main_protected_function> mRegisteredCallbacks;
std::map<int64_t, sol::main_protected_function> mTemporaryCallbacks; std::map<int64_t, sol::main_protected_function> mTemporaryCallbacks;
VFS::Path::Normalized mPath; VFS::Path::Normalized mPath;
@ -268,11 +268,11 @@ namespace LuaUtil
const UserdataSerializer* mSerializer = nullptr; const UserdataSerializer* mSerializer = nullptr;
const UserdataSerializer* mSavedDataDeserializer = nullptr; const UserdataSerializer* mSavedDataDeserializer = nullptr;
std::map<std::string, sol::object> mAPI; std::map<std::string, sol::main_object> mAPI;
struct LoadedData struct LoadedData
{ {
std::map<int, Script> mScripts; std::map<int, Script> mScripts;
sol::table mPublicInterfaces; sol::main_table mPublicInterfaces;
std::map<std::string, EventHandlerList, std::less<>> mEventHandlers; std::map<std::string, EventHandlerList, std::less<>> mEventHandlers;

View file

@ -37,7 +37,7 @@ namespace LuaUtil
sol::object LuaStorage::Value::getReadOnly(lua_State* L) const sol::object LuaStorage::Value::getReadOnly(lua_State* L) const
{ {
if (mReadOnlyValue == sol::nil && !mSerializedValue.empty()) if (mReadOnlyValue == sol::nil && !mSerializedValue.empty())
mReadOnlyValue = deserialize(L, mSerializedValue, nullptr, true); mReadOnlyValue = sol::main_object(deserialize(L, mSerializedValue, nullptr, true));
return mReadOnlyValue; return mReadOnlyValue;
} }

View file

@ -74,7 +74,7 @@ namespace LuaUtil
private: private:
std::string mSerializedValue; std::string mSerializedValue;
mutable sol::object mReadOnlyValue = sol::nil; mutable sol::main_object mReadOnlyValue = sol::nil;
}; };
struct Section struct Section

View file

@ -18,7 +18,7 @@ namespace LuaUi
{ {
public: public:
// accepts only Lua tables returned by ui.content // accepts only Lua tables returned by ui.content
explicit ContentView(sol::table table) explicit ContentView(sol::main_table table)
: mTable(std::move(table)) : mTable(std::move(table))
{ {
if (!isValidContent(mTable)) if (!isValidContent(mTable))
@ -94,7 +94,7 @@ namespace LuaUi
sol::table getMetatable() const { return mTable[sol::metatable_key].get<sol::table>(); } sol::table getMetatable() const { return mTable[sol::metatable_key].get<sol::table>(); }
private: private:
sol::table mTable; sol::main_table mTable;
template <typename... Arg> template <typename... Arg>
sol::object callMethod(std::string_view name, Arg&&... arg) const sol::object callMethod(std::string_view name, Arg&&... arg) const

View file

@ -324,7 +324,7 @@ namespace LuaUi
destroyRoot(mRoot); destroyRoot(mRoot);
mRoot = nullptr; mRoot = nullptr;
} }
mLayout = sol::make_object(mLayout.lua_state(), sol::nil); mLayout.reset();
} }
mState = Destroyed; mState = Destroyed;
} }

View file

@ -19,7 +19,7 @@ namespace LuaUi
} }
WidgetExtension* mRoot; WidgetExtension* mRoot;
sol::object mLayout; sol::main_object mLayout;
std::string mLayer; std::string mLayer;
enum State enum State

View file

@ -281,7 +281,7 @@ namespace LuaUi
updateChildrenCoord(); updateChildrenCoord();
} }
void WidgetExtension::setProperties(const sol::object& props) void WidgetExtension::setProperties(const sol::main_object& props)
{ {
mProperties = props; mProperties = props;
updateProperties(); updateProperties();

View file

@ -50,10 +50,10 @@ namespace LuaUi
void setCallback(const std::string&, const LuaUtil::Callback&); void setCallback(const std::string&, const LuaUtil::Callback&);
void clearCallbacks(); void clearCallbacks();
void setProperties(const sol::object& props); void setProperties(const sol::main_object& props);
void setTemplateProperties(const sol::object& props) { mTemplateProperties = props; } void setTemplateProperties(const sol::main_object& props) { mTemplateProperties = props; }
void setExternal(const sol::object& external) { mExternal = external; } void setExternal(const sol::main_object& external) { mExternal = external; }
MyGUI::IntCoord forcedCoord(); MyGUI::IntCoord forcedCoord();
void forceCoord(const MyGUI::IntCoord& offset); void forceCoord(const MyGUI::IntCoord& offset);
@ -63,7 +63,7 @@ namespace LuaUi
virtual void updateCoord(); virtual void updateCoord();
const sol::table& getLayout() { return mLayout; } const sol::main_table& getLayout() { return mLayout; }
void setLayout(const sol::table& layout) { mLayout = layout; } void setLayout(const sol::table& layout) { mLayout = layout; }
template <typename T> template <typename T>
@ -150,10 +150,10 @@ namespace LuaUi
std::vector<WidgetExtension*> mTemplateChildren; std::vector<WidgetExtension*> mTemplateChildren;
WidgetExtension* mSlot; WidgetExtension* mSlot;
std::map<std::string, LuaUtil::Callback, std::less<>> mCallbacks; std::map<std::string, LuaUtil::Callback, std::less<>> mCallbacks;
sol::table mLayout; sol::main_table mLayout;
sol::object mProperties; sol::main_object mProperties;
sol::object mTemplateProperties; sol::main_object mTemplateProperties;
sol::object mExternal; sol::main_object mExternal;
WidgetExtension* mParent; WidgetExtension* mParent;
bool mTemplateChild; bool mTemplateChild;
bool mElementRoot; bool mElementRoot;