1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-14 15:40:18 +00:00

Return nil when we try to use an invalid store index from Lua

This commit is contained in:
Andrei Kortunov 2023-09-08 09:25:13 +04:00
parent 690a237896
commit 5d211d3c93
6 changed files with 42 additions and 24 deletions

View File

@ -231,7 +231,11 @@ namespace MWLua
sol::usertype<CellsStore> cells = context.mLua->sol().new_usertype<CellsStore>("Cells");
cells[sol::meta_function::length]
= [cells3Store, cells4Store](const CellsStore&) { return cells3Store->getSize() + cells4Store->getSize(); };
cells[sol::meta_function::index] = [cells3Store, cells4Store](const CellsStore&, size_t index) -> GCell {
cells[sol::meta_function::index]
= [cells3Store, cells4Store](const CellsStore&, size_t index) -> sol::optional<GCell> {
if (index > cells3Store->getSize() + cells3Store->getSize() || index == 0)
return sol::nullopt;
index--; // Translate from Lua's 1-based indexing.
if (index < cells3Store->getSize())
{

View File

@ -243,9 +243,13 @@ namespace MWLua
= [](const SpellStore& store) { return "ESM3_SpellStore{" + std::to_string(store.getSize()) + " spells}"; };
spellStoreT[sol::meta_function::length] = [](const SpellStore& store) { return store.getSize(); };
spellStoreT[sol::meta_function::index] = sol::overload(
[](const SpellStore& store, size_t index) -> const ESM::Spell* { return store.at(index - 1); },
[](const SpellStore& store, size_t index) -> const ESM::Spell* {
if (index == 0 || index > store.getSize())
return nullptr;
return store.at(index - 1);
},
[](const SpellStore& store, std::string_view spellId) -> const ESM::Spell* {
return store.find(ESM::RefId::deserializeText(spellId));
return store.search(ESM::RefId::deserializeText(spellId));
});
spellStoreT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>();
spellStoreT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>();
@ -262,9 +266,13 @@ namespace MWLua
};
enchantmentStoreT[sol::meta_function::length] = [](const EnchantmentStore& store) { return store.getSize(); };
enchantmentStoreT[sol::meta_function::index] = sol::overload(
[](const EnchantmentStore& store, size_t index) -> const ESM::Enchantment* { return store.at(index - 1); },
[](const EnchantmentStore& store, size_t index) -> const ESM::Enchantment* {
if (index == 0 || index > store.getSize())
return nullptr;
return store.at(index - 1);
},
[](const EnchantmentStore& store, std::string_view enchantmentId) -> const ESM::Enchantment* {
return store.find(ESM::RefId::deserializeText(enchantmentId));
return store.search(ESM::RefId::deserializeText(enchantmentId));
});
enchantmentStoreT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>();
enchantmentStoreT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>();
@ -280,10 +288,10 @@ namespace MWLua
return "ESM3_MagicEffectStore{" + std::to_string(store.getSize()) + " effects}";
};
magicEffectStoreT[sol::meta_function::index] = sol::overload(
[](const MagicEffectStore& store, int id) -> const ESM::MagicEffect* { return store.find(id); },
[](const MagicEffectStore& store, int id) -> const ESM::MagicEffect* { return store.search(id); },
[](const MagicEffectStore& store, std::string_view id) -> const ESM::MagicEffect* {
int index = ESM::MagicEffect::indexNameToIndex(id);
return store.find(index);
return store.search(index);
});
auto magicEffectsIter = [magicEffectStore](sol::this_state lua, const sol::object& /*store*/,
sol::optional<int> id) -> std::tuple<sol::object, sol::object> {
@ -665,20 +673,20 @@ namespace MWLua
// types.Actor.spells(o)[i]
spellsT[sol::meta_function::index] = sol::overload(
[](const ActorSpells& spells, size_t index) -> sol::optional<const ESM::Spell*> {
[](const ActorSpells& spells, size_t index) -> const ESM::Spell* {
if (auto* store = spells.getStore())
if (index <= store->count())
if (index <= store->count() && index > 0)
return store->at(index - 1);
return sol::nullopt;
return nullptr;
},
[spellStore](const ActorSpells& spells, std::string_view spellId) -> sol::optional<const ESM::Spell*> {
[spellStore](const ActorSpells& spells, std::string_view spellId) -> const ESM::Spell* {
if (auto* store = spells.getStore())
{
const ESM::Spell* spell = spellStore->find(ESM::RefId::deserializeText(spellId));
if (store->hasSpell(spell))
const ESM::Spell* spell = spellStore->search(ESM::RefId::deserializeText(spellId));
if (spell && store->hasSpell(spell))
return spell;
}
return sol::nullopt;
return nullptr;
});
// pairs(types.Actor.spells(o))

View File

@ -136,11 +136,11 @@ namespace MWLua
listT[sol::meta_function::to_string]
= [](const ListT& list) { return "{" + std::to_string(list.mIds->size()) + " objects}"; };
listT[sol::meta_function::length] = [](const ListT& list) { return list.mIds->size(); };
listT[sol::meta_function::index] = [](const ListT& list, size_t index) {
listT[sol::meta_function::index] = [](const ListT& list, size_t index) -> sol::optional<ObjectT> {
if (index > 0 && index <= list.mIds->size())
return ObjectT((*list.mIds)[index - 1]);
else
throw std::runtime_error("Index out of range");
return sol::nullopt;
};
listT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>();
listT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>();

View File

@ -169,9 +169,13 @@ namespace MWLua
= [](const SoundStore& store) { return "ESM3_SoundStore{" + std::to_string(store.getSize()) + " sounds}"; };
soundStoreT[sol::meta_function::length] = [](const SoundStore& store) { return store.getSize(); };
soundStoreT[sol::meta_function::index] = sol::overload(
[](const SoundStore& store, size_t index) -> const ESM::Sound* { return store.at(index - 1); },
[](const SoundStore& store, size_t index) -> const ESM::Sound* {
if (index == 0 || index > store.getSize())
return nullptr;
return store.at(index - 1);
},
[](const SoundStore& store, std::string_view soundId) -> const ESM::Sound* {
return store.find(ESM::RefId::deserializeText(soundId));
return store.search(ESM::RefId::deserializeText(soundId));
});
soundStoreT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>();
soundStoreT[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>();

View File

@ -48,13 +48,13 @@ namespace MWLua
};
sol::usertype<Quests> quests = context.mLua->sol().new_usertype<Quests>("Quests");
quests[sol::meta_function::to_string] = [](const Quests& quests) { return "Quests"; };
quests[sol::meta_function::index] = sol::overload([](const Quests& quests, std::string_view questId) -> Quest {
quests[sol::meta_function::index] = [](const Quests& quests, std::string_view questId) -> sol::optional<Quest> {
ESM::RefId quest = ESM::RefId::deserializeText(questId);
const ESM::Dialogue* dial = MWBase::Environment::get().getESMStore()->get<ESM::Dialogue>().find(quest);
if (dial->mType != ESM::Dialogue::Journal)
throw std::runtime_error("Not a quest:" + std::string(questId));
const ESM::Dialogue* dial = MWBase::Environment::get().getESMStore()->get<ESM::Dialogue>().search(quest);
if (dial == nullptr || dial->mType != ESM::Dialogue::Journal)
return sol::nullopt;
return Quest{ .mQuestId = quest, .mMutable = quests.mMutable };
});
};
quests[sol::meta_function::pairs] = [journal](const Quests& quests) {
std::vector<ESM::RefId> ids;
for (auto it = journal->questBegin(); it != journal->questEnd(); ++it)

View File

@ -77,7 +77,7 @@ namespace MWLua
const MWWorld::Store<T>& store = MWBase::Environment::get().getESMStore()->get<T>();
table["record"] = sol::overload([](const Object& obj) -> const T* { return obj.ptr().get<T>()->mBase; },
[&store](std::string_view id) -> const T* { return store.find(ESM::RefId::deserializeText(id)); });
[&store](std::string_view id) -> const T* { return store.search(ESM::RefId::deserializeText(id)); });
// Define a custom user type for the store.
// Provide the interface of a read-only array.
@ -89,6 +89,8 @@ namespace MWLua
};
storeT[sol::meta_function::length] = [](const StoreT& store) { return store.getSize(); };
storeT[sol::meta_function::index] = [](const StoreT& store, size_t index) -> const T* {
if (index == 0 || index > store.getSize())
return nullptr;
return store.at(index - 1); // Translate from Lua's 1-based indexing.
};
storeT[sol::meta_function::pairs] = lua["ipairsForArray"].template get<sol::function>();