Skip to content

Commit 9d4f7ea

Browse files
committed
Fix pcall()/xpcall() bug.
1 parent 3ceac70 commit 9d4f7ea

File tree

1 file changed

+24
-11
lines changed

1 file changed

+24
-11
lines changed

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

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,10 @@ sandbox = {
761761
next = next,
762762
pairs = pairs,
763763
pcall = function(...)
764+
-- prevent infinite pcall() loops by checking deadline before pcall()
765+
local status, err = pcall(checkDeadline)
766+
if not status then return false, err end
767+
764768
return pcallTimeoutCheck(pcall(...))
765769
end,
766770
print = nil, -- in boot/*_base.lua
@@ -807,18 +811,27 @@ sandbox = {
807811
type = type,
808812
_VERSION = _VERSION:match("Luaj") and "Luaj" or _VERSION:match("5.4") and "Lua 5.4" or _VERSION:match("5.3") and "Lua 5.3" or "Lua 5.2",
809813
xpcall = function(f, msgh, ...)
810-
local handled = false
814+
-- allow xpcall() to call the message handler recursively, per manual 2.3
815+
-- Lua itself promises to break the infinite loop; failing that, the timeout
816+
-- check will take care of this.
817+
local errorCapture
818+
errorCapture = function(ff, ...)
819+
-- prevent infinite xpcall() loops by checking deadline before xpcall()
820+
local status, err = pcall(checkDeadline)
821+
if not status then return false, err end
822+
823+
return xpcall(ff, function(...)
824+
if rawequal((...), tooLongWithoutYielding) then
825+
return tooLongWithoutYielding
826+
else
827+
return select(2, errorCapture(msgh, ...))
828+
end
829+
end, ...)
830+
end
831+
811832
checkArg(2, msgh, "function")
812-
local result = table.pack(xpcall(f, function(...)
813-
if rawequal((...), tooLongWithoutYielding) then
814-
return tooLongWithoutYielding
815-
elseif handled then
816-
return ...
817-
else
818-
handled = true
819-
return msgh(...)
820-
end
821-
end, ...))
833+
local result = table.pack(errorCapture(f, ...))
834+
-- if the final returned error is due to timeout, run handler one last time
822835
if rawequal(result[2], tooLongWithoutYielding) then
823836
result = table.pack(result[1], select(2, pcallTimeoutCheck(pcall(msgh, tostring(tooLongWithoutYielding)))))
824837
end

0 commit comments

Comments
 (0)