From 909470be9f7ec1dd2d09ae1a371d69c9c652e957 Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Sat, 26 Jun 2021 18:25:53 +0200 Subject: fix stack overflow when transfering a clonable userdata referencing itself through a uservalue --- deep_test/deep_test.c | 2 ++ deep_test/deep_test.vcxproj | 5 +++++ deep_test/deep_test.vcxproj.user | 6 +++++ deep_test/deeptest.lua | 47 ++++++++++++++++++++++++++++------------ 4 files changed, 46 insertions(+), 14 deletions(-) (limited to 'deep_test') diff --git a/deep_test/deep_test.c b/deep_test/deep_test.c index dabc84d..873428b 100644 --- a/deep_test/deep_test.c +++ b/deep_test/deep_test.c @@ -16,6 +16,7 @@ // ################################################################################################ +// a lanes-deep userdata. needs DeepPrelude and luaG_newdeepuserdata from Lanes code. struct s_MyDeepUserdata { DeepPrelude prelude; // Deep userdata MUST start with this header @@ -190,6 +191,7 @@ static int clonable_gc( lua_State* L) // ################################################################################################ +// this is all we need to make a userdata lanes-clonable. no dependency on Lanes code. static int clonable_lanesclone( lua_State* L) { switch( lua_gettop( L)) diff --git a/deep_test/deep_test.vcxproj b/deep_test/deep_test.vcxproj index 67d3afd..6e25b9a 100644 --- a/deep_test/deep_test.vcxproj +++ b/deep_test/deep_test.vcxproj @@ -115,6 +115,10 @@ $(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\ $(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\ + + $(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\ + $(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\ + Level3 @@ -125,6 +129,7 @@ true $(SolutionDir)Lanes\lanes\src;$(SolutionDir)..\lualib;%(AdditionalIncludeDirectories) $(IntDir)$(TargetName).pdb + _WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true diff --git a/deep_test/deep_test.vcxproj.user b/deep_test/deep_test.vcxproj.user index 70871df..9195f89 100644 --- a/deep_test/deep_test.vcxproj.user +++ b/deep_test/deep_test.vcxproj.user @@ -12,4 +12,10 @@ -i deeptest.lua D:\Boulot\anubis\Lua\bindings\Lanes\lanes\deep_test\ + + D:\Boulot\anubis\Lua\framework\lua53.exe + WindowsLocalDebugger + -i -- deeptest.lua + D:\Boulot\anubis\Lua\bindings\Lanes\lanes\deep_test\ + \ No newline at end of file diff --git a/deep_test/deeptest.lua b/deep_test/deeptest.lua index 92cd372..3c89c3d 100644 --- a/deep_test/deeptest.lua +++ b/deep_test/deeptest.lua @@ -5,8 +5,8 @@ local l = lanes.linda "my linda" local dt = lanes.require "deep_test" local test_deep = true -local test_clonable = false -local test_uvtype = "string" +local test_clonable = true +local test_uvtype = "function" local makeUserValue = function( obj_) if test_uvtype == "string" then @@ -14,12 +14,23 @@ local makeUserValue = function( obj_) elseif test_uvtype == "function" then -- a function that pull the userdata as upvalue local f = function() - print( obj_) + return tostring( obj_) end return f end end +local printDeep = function( prefix_, obj_, t_) + local uservalue = obj_:getuv( 1) + print( prefix_) + print ( obj_, uservalue, type( uservalue) == "function" and uservalue() or "") + if t_ then + for k, v in pairs( t_) do + print( k, v) + end + end +end + local performTest = function( obj_) -- setup the userdata with some value and a uservalue obj_:set( 666) @@ -29,15 +40,20 @@ local performTest = function( obj_) -- lua 5.4 supports multiple uservalues of arbitrary types -- obj_:setuv( 2, "ENDUV") + local t = + { + ["key"] = obj_, + -- [obj_] = "val" + } + -- read back the contents of the object - print( "immediate:", obj_, obj_:getuv( 1)) + printDeep( "immediate:", obj_, t) -- send the object in a linda, get it back out, read the contents - l:set( "key", obj_) + l:set( "key", obj_, t) -- when obj_ is a deep userdata, out is the same userdata as obj_ (not another one pointing on the same deep memory block) because of an internal cache table [deep*] -> proxy) -- when obj_ is a clonable userdata, we get a different clone everytime we cross a linda or lane barrier - local out = l:get( "key") - print( "out of linda:", out, out:getuv( 1)) + printDeep( "out of linda:", l:get( "key", 2)) -- send the object in a lane through parameter passing, the lane body returns it as return value, read the contents local g = lanes.gen( @@ -45,23 +61,26 @@ local performTest = function( obj_) , { required = { "deep_test"} -- we will transfer userdata created by this module, so we need to make this lane aware of it } - , function( param_) - -- read contents inside lane - print( "in lane:", param_, param_:getuv( 1)) - return param_ + , function( arg_, t_) + -- read contents inside lane: arg_ and t_ by argument + printDeep( "in lane, as arguments:", arg_, t_) + -- read contents inside lane: obj_ and t by upvalue + printDeep( "in lane, as upvalues:", obj_, t) + return arg_, t_ end ) - h = g( obj_) + h = g( obj_, t) -- when obj_ is a deep userdata, from_lane is the same userdata as obj_ (not another one pointing on the same deep memory block) because of an internal cache table [deep*] -> proxy) -- when obj_ is a clonable userdata, we get a different clone everytime we cross a linda or lane barrier - local from_lane = h[1] - print( "from lane:", from_lane, from_lane:getuv( 1)) + printDeep( "from lane:", h[1], h[2]) end if test_deep then + print "DEEP" performTest( dt.new_deep()) end if test_clonable then + print "CLONABLE" performTest( dt.new_clonable()) end -- cgit v1.2.3-55-g6feb