Skip to content

Commit

Permalink
Fix pcall()/xpcall() bug.
Browse files Browse the repository at this point in the history
  • Loading branch information
asiekierka committed Apr 16, 2024
1 parent 3ceac70 commit 9d4f7ea
Showing 1 changed file with 24 additions and 11 deletions.
35 changes: 24 additions & 11 deletions src/main/resources/assets/opencomputers/lua/machine.lua
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,10 @@ sandbox = {
next = next,
pairs = pairs,
pcall = function(...)
-- prevent infinite pcall() loops by checking deadline before pcall()
local status, err = pcall(checkDeadline)
if not status then return false, err end

return pcallTimeoutCheck(pcall(...))
end,
print = nil, -- in boot/*_base.lua
Expand Down Expand Up @@ -807,18 +811,27 @@ sandbox = {
type = type,
_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",
xpcall = function(f, msgh, ...)
local handled = false
-- allow xpcall() to call the message handler recursively, per manual 2.3
-- Lua itself promises to break the infinite loop; failing that, the timeout
-- check will take care of this.
local errorCapture
errorCapture = function(ff, ...)
-- prevent infinite xpcall() loops by checking deadline before xpcall()
local status, err = pcall(checkDeadline)
if not status then return false, err end

return xpcall(ff, function(...)
if rawequal((...), tooLongWithoutYielding) then
return tooLongWithoutYielding
else
return select(2, errorCapture(msgh, ...))
end
end, ...)
end

checkArg(2, msgh, "function")
local result = table.pack(xpcall(f, function(...)
if rawequal((...), tooLongWithoutYielding) then
return tooLongWithoutYielding
elseif handled then
return ...
else
handled = true
return msgh(...)
end
end, ...))
local result = table.pack(errorCapture(f, ...))
-- if the final returned error is due to timeout, run handler one last time
if rawequal(result[2], tooLongWithoutYielding) then
result = table.pack(result[1], select(2, pcallTimeoutCheck(pcall(msgh, tostring(tooLongWithoutYielding)))))
end
Expand Down

0 comments on commit 9d4f7ea

Please sign in to comment.