-
-
Notifications
You must be signed in to change notification settings - Fork 588
Fix memory leak when indexing user types #1716
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
…revent implicit conversion of stack_reference to stateless_reference
|
This doesn't work before C++ 20, because these lack support for transparent lookup in diff --git a/include/sol/usertype_storage.hpp b/include/sol/usertype_storage.hpp
index bdca6146..691a025b 100644
--- a/include/sol/usertype_storage.hpp
+++ b/include/sol/usertype_storage.hpp
@@ -502,7 +502,11 @@ namespace sol { namespace u_detail {
stateless_reference* target = nullptr;
{
stack_reference k = stack::get<stack_reference>(L, 2);
+#if __cpp_lib_generic_unordered_lookup >= 201811L
auto it = self.auxiliary_keys.find(k);
+#else
+ auto it = self.auxiliary_keys.find(basic_reference(k));
+#endif
if (it != self.auxiliary_keys.cend()) {
target = &it->second;
}A test (based on one example) to ensure this doesn't happen again: Test#include <catch2/catch_all.hpp>
#include <sol/sol.hpp>
TEST_CASE("#1716 - index and newindex should not leak values into the registry", "[sol2][regression][issue1716]") {
class vector {
public:
vector() = default;
static int my_index(vector&, int) {
return 0;
}
static void my_new_index(vector&, int, int) {
return;
}
};
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<vector>("vector",
sol::constructors<sol::types<>>(), //
sol::meta_function::index,
&vector::my_index, //
sol::meta_function::new_index,
&vector::my_new_index);
auto begin = lua.registry().size();
lua.script(R"(
local v = vector.new()
local unused = 0
for i=1,100 do
unused = v[1]
v[1] = 1
end
)");
REQUIRE(lua.registry().size() <= begin + 1);
} |
|
Oh right, C++17. Thanks. I've added your changes. |
100/5000 |
Did you apply the full PR (https://github.com/ThePhD/sol2/pull/1716.patch)? With MSVC and C++ 20, I don't get any test failures and the added test runs: > cmake -B build-20 -DCMAKE_CXX_STANDARD=20 -DSOL2_LUA_VERSION="5.4.8" -DSOL2_BUILD_LUA=On -DSOL2_TESTS=On -DSOL2_CI=On -DBUILD_LUA_AS_DLL=Off -G Ninja
> ninja -C build-20
> ctest --test-dir build-20 -j 20
...
20/25 Test #22: sol2.tests.regression_1716 ................................. Passed 0.10 sec
21/25 Test #23: sol2.tests.regression_1716.SOL_ALL_SAFETIES_ON ............. Passed 0.08 sec
... |
sol::u_detail::usertype_storage_base::self_index_callcontainsauto it = self.auxiliary_keys.find(k).kis astack_referenceandauxiliary_keysan unordered map withstateless_referencekeys.When compiled with Visual Studio 2022,
kis implicitly converted to astateless_referenceviastateless_reference(const stack_reference&)andstateless_reference(lua_State*, int). The latter adds a reference to the registry throughref = luaL_ref(L_, LUA_REGISTRYINDEX), butstateless_reference's destructor doesn't callderefso the registry table retains the value even after the call tofindcompletes.I don't know if
stateless_referenceshould have a destructor that takes care of this. If not, I'd say its constructors should probably be markedexplicitto avoid doing this by accident. Regardless, this PR skirts around that by avoiding the conversion in the first place. Which seems desirable.I don't know if this affects other compilers/standard libraries/code paths. @magicaldave's comment on https://gitlab.com/OpenMW/openmw/-/issues/8614 suggests that some platforms might be unaffected.