From b40f895fd409bf93f6e4278e73d65bf1eac3b72b Mon Sep 17 00:00:00 2001 From: ThePhD Date: Wed, 23 Nov 2016 02:39:52 -0500 Subject: [PATCH] Fix double-delete crash that could also be affecting @IronsDu --- single/sol/sol.hpp | 9 ++++----- sol/stack_core.hpp | 2 +- sol/stack_push.hpp | 3 +-- test_functions.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/single/sol/sol.hpp b/single/sol/sol.hpp index b4922981..72eba463 100644 --- a/single/sol/sol.hpp +++ b/single/sol/sol.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2016-11-18 05:05:58.487868 UTC -// This header was generated with sol v2.15.1 (revision 97cafba) +// Generated 2016-11-23 07:39:25.032134 UTC +// This header was generated with sol v2.15.1 (revision 320276d) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -4139,7 +4139,7 @@ namespace sol { template inline int user_alloc_destroy(lua_State* L) { - void* rawdata = lua_touserdata(L, upvalue_index(1)); + void* rawdata = lua_touserdata(L, 1); T* data = static_cast(rawdata); std::allocator alloc; alloc.destroy(data); @@ -6176,8 +6176,7 @@ namespace sol { lua_CFunction cdel = detail::user_alloc_destroy; // Make sure we have a plain GC set for this data if (luaL_newmetatable(L, name) != 0) { - lua_pushlightuserdata(L, rawdata); - lua_pushcclosure(L, cdel, 1); + lua_pushcclosure(L, cdel, 0); lua_setfield(L, -2, "__gc"); } lua_setmetatable(L, -2); diff --git a/sol/stack_core.hpp b/sol/stack_core.hpp index 910399f3..13fad796 100644 --- a/sol/stack_core.hpp +++ b/sol/stack_core.hpp @@ -62,7 +62,7 @@ namespace sol { template inline int user_alloc_destroy(lua_State* L) { - void* rawdata = lua_touserdata(L, upvalue_index(1)); + void* rawdata = lua_touserdata(L, 1); T* data = static_cast(rawdata); std::allocator alloc; alloc.destroy(data); diff --git a/sol/stack_push.hpp b/sol/stack_push.hpp index 0478bcbe..1c86d616 100644 --- a/sol/stack_push.hpp +++ b/sol/stack_push.hpp @@ -351,8 +351,7 @@ namespace sol { lua_CFunction cdel = detail::user_alloc_destroy; // Make sure we have a plain GC set for this data if (luaL_newmetatable(L, name) != 0) { - lua_pushlightuserdata(L, rawdata); - lua_pushcclosure(L, cdel, 1); + lua_pushcclosure(L, cdel, 0); lua_setfield(L, -2, "__gc"); } lua_setmetatable(L, -2); diff --git a/test_functions.cpp b/test_functions.cpp index 60a3c702..ea6915cf 100644 --- a/test_functions.cpp +++ b/test_functions.cpp @@ -947,3 +947,43 @@ TEST_CASE("functions/stack-protect", "make sure functions don't impede on the st } REQUIRE(sg.check_stack()); } + +TEST_CASE("functions/same-type-closures", "make sure destructions are per-object, not per-type, by destroying one type multiple times") { + static std::set last_my_closures; + static bool checking_closures = false; + static bool check_failed = false; + + struct my_closure { + int& n; + + my_closure(int& n) : n(n) {} + ~my_closure() noexcept(false) { + if (!checking_closures) + return; + void* addr = static_cast(this); + auto f = last_my_closures.find(addr); + if (f != last_my_closures.cend()) { + check_failed = true; + } + last_my_closures.insert(f, addr); + } + + int operator() () { + ++n; return n; + } + + }; + + int n = 250; + my_closure a(n); + my_closure b(n); + { + sol::state lua; + + lua.set_function("f", a); + lua.set_function("g", b); + checking_closures = true; + } + REQUIRE_FALSE(check_failed); + REQUIRE(last_my_closures.size() == 2); +}