From 07f452125c9795a9a36da2dee4f9e465ea9b6bb9 Mon Sep 17 00:00:00 2001 From: Soni L Date: Sun, 31 Jan 2016 14:46:52 -0200 Subject: [PATCH] Fix __gc and use raw metatable when it's disabled This fixes a small __gc abuse I found, and also uses the raw metatable in a safe way when __gc is disabled. Both were tested. --- .../assets/opencomputers/lua/machine.lua | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/main/resources/assets/opencomputers/lua/machine.lua b/src/main/resources/assets/opencomputers/lua/machine.lua index a2617aa1b..baf883485 100644 --- a/src/main/resources/assets/opencomputers/lua/machine.lua +++ b/src/main/resources/assets/opencomputers/lua/machine.lua @@ -683,7 +683,7 @@ sandbox = { end local result = getmetatable(t) -- check if we have a wrapped __gc using mt - if type(result) == "table" and rawget(result, "__gc") == sgc then + if type(result) == "table" and system.allowGC() and rawget(result, "__gc") == sgc then result = rawget(result, "mt") end return result @@ -713,26 +713,32 @@ sandbox = { if type(mt) ~= "table" then return setmetatable(t, mt) end - if type(rawget(mt, "__gc")) == "function" then - -- For all user __gc functions we enforce a much tighter deadline. - -- This is because these functions may be called from the main - -- thread under certain circumstanced (such as when saving the world), - -- which can lead to noticeable lag if the __gc function behaves badly. - local sbmt = {} -- sandboxed metatable. only for __gc stuff, so it's - -- kinda ok to have a shallow copy instead... meh. - for k, v in next, mt do - sbmt[k] = v - end - sbmt.mt = mt + if rawget(mt, "__gc") ~= nil then -- If __gc is set to ANYTHING not `nil`, we're gonna have issues -- Garbage collector callbacks apparently can't be sandboxed after -- all, because hooks are disabled while they're running. So we just -- disable them altogether by default. - if not system.allowGC() then - sbmt.__gc = nil -- Silent fail for backwards compat. TODO error in OC 1.7 - else + if system.allowGC() then + -- For all user __gc functions we enforce a much tighter deadline. + -- This is because these functions may be called from the main + -- thread under certain circumstanced (such as when saving the world), + -- which can lead to noticeable lag if the __gc function behaves badly. + local sbmt = {} -- sandboxed metatable. only for __gc stuff, so it's + -- kinda ok to have a shallow copy instead... meh. + for k, v in next, mt do + sbmt[k] = v + end sbmt.__gc = sgc + sbmt.mt = mt + mt = sbmt + else + -- Don't allow marking for finalization, but use the raw metatable. + local gc = rawget(mt, "__gc") + rawset(mt, "__gc", nil) -- remove __gc + local ret = table.pack(pcall(setmetatable, t, mt)) + rawset(mt, "__gc", gc) -- restore __gc + if not ret[1] then error(ret[2], 0) end + return table.unpack(ret, 1, ret.n) end - mt = sbmt end return setmetatable(t, mt) end, @@ -1442,4 +1448,4 @@ end -- JNLua converts the coroutine to a string immediately, so we can't get the -- traceback later. Because of that we have to do the error handling here. -return pcall(main) \ No newline at end of file +return pcall(main)