Skip to content

Commit d4addfd

Browse files
SoniEx2fnuecke
authored andcommitted
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. # Conflicts: # src/main/resources/assets/opencomputers/lua/machine.lua
1 parent 0f01f6d commit d4addfd

File tree

1 file changed

+16
-10
lines changed

1 file changed

+16
-10
lines changed

src/main/resources/assets/opencomputers/lua/machine.lua

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,7 @@ sandbox = {
683683
end
684684
local result = getmetatable(t)
685685
-- check if we have a wrapped __gc using mt
686-
if type(result) == "table" and rawget(result, "__gc") == sgc then
686+
if type(result) == "table" and system.allowGC() and rawget(result, "__gc") == sgc then
687687
result = rawget(result, "mt")
688688
end
689689
return result
@@ -713,7 +713,11 @@ sandbox = {
713713
if type(mt) ~= "table" then
714714
return setmetatable(t, mt)
715715
end
716-
if type(rawget(mt, "__gc")) == "function" then
716+
if rawget(mt, "__gc") ~= nil then -- If __gc is set to ANYTHING not `nil`, we're gonna have issues
717+
-- Garbage collector callbacks apparently can't be sandboxed after
718+
-- all, because hooks are disabled while they're running. So we just
719+
-- disable them altogether by default.
720+
if system.allowGC() then
717721
-- For all user __gc functions we enforce a much tighter deadline.
718722
-- This is because these functions may be called from the main
719723
-- thread under certain circumstanced (such as when saving the world),
@@ -723,16 +727,18 @@ sandbox = {
723727
for k, v in pairs(mt) do
724728
sbmt[k] = v
725729
end
730+
sbmt.__gc = sgc
726731
sbmt.mt = mt
727-
-- Garbage collector callbacks apparently can't be sandboxed after
728-
-- all, because hooks are disabled while they're running. So we just
729-
-- disable them altogether by default.
730-
if not system.allowGC() then
731-
sbmt.__gc = nil -- Silent fail for backwards compat. TODO error in OC 1.7
732+
mt = sbmt
732733
else
733-
sbmt.__gc = sgc
734+
-- Don't allow marking for finalization, but use the raw metatable.
735+
local gc = rawget(mt, "__gc")
736+
rawset(mt, "__gc", nil) -- remove __gc
737+
local ret = table.pack(pcall(setmetatable, t, mt))
738+
rawset(mt, "__gc", gc) -- restore __gc
739+
if not ret[1] then error(ret[2], 0) end
740+
return table.unpack(ret, 1, ret.n)
734741
end
735-
mt = sbmt
736742
end
737743
return setmetatable(t, mt)
738744
end,
@@ -1442,4 +1448,4 @@ end
14421448

14431449
-- JNLua converts the coroutine to a string immediately, so we can't get the
14441450
-- traceback later. Because of that we have to do the error handling here.
1445-
return pcall(main)
1451+
return pcall(main)

0 commit comments

Comments
 (0)