/usr/lib/ruby/vendor_ruby/wikicloth/extensions/lua/luawrapper.lua is in ruby-wikicloth 0.8.1+dfsg-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | -- Lua parser extensions for MediaWiki - Wrapper for Lua interpreter
-- (c) 2008 Fran Rogers - see 'COPYING' for license
-- Creates a new sandbox environment for scripts to safely run in.
function make_sandbox()
-- Dummy function that returns nil, to quietly replace unsafe functions
local function dummy(...)
return nil
end
-- Deep-copy an object; optionally replace all its leaf members with the
-- value 'override' if it's non-nil
local function deepcopy(object, override)
local lookup_table = {}
local function _copy(object, override)
if type(object) ~= "table" then
return object
elseif lookup_table[object] then
return lookup_table[object]
end
local new_table = {}
lookup_table[object] = new_table
for index, value in pairs(object) do
if override ~= nil then
value = override
end
new_table[_copy(index)] = _copy(value, override)
end
return setmetatable(new_table, _copy(getmetatable(object), override))
end
return _copy(object, override)
end
-- Our new environment
local env = {}
-- "_OUTPUT" will accumulate the results of print() and friends
env._OUTPUT = ""
-- _OUTPUT wrapper for io.write()
local function writewrapper(...)
local out = ""
for n = 1, select("#", ...) do
if out == "" then
out = tostring(select(n, ...))
else
out = out .. tostring(select(n, ...))
end
end
env._OUTPUT = env._OUTPUT .. out
end
-- _OUTPUT wrapper for io.stdout:output()
local function outputwrapper(file)
if file == nil then
local file = {}
file.close = dummy
file.lines = dummy
file.read = dummy
file.flush = dummy
file.seek = dummy
file.setvbuf = dummy
function file:write(...) writewrapper(...); end
return file
else
return nil
end
end
-- _OUTPUT wrapper for print()
local function printwrapper(...)
local out = ""
for n = 1, select("#", ...) do
if out == "" then
out = tostring(select(n, ...))
else
out = out .. '\t' .. tostring(select(n, ...))
end
end
env._OUTPUT =env._OUTPUT .. out .. "\n"
end
-- Safe wrapper for loadstring()
local oldloadstring = loadstring
local function safeloadstring(s, chunkname)
local f, message = oldloadstring(s, chunkname)
if not f then
return f, message
end
setfenv(f, getfenv(2))
return f
end
-- Populate the sandbox environment
env.assert = _G.assert
env.error = _G.error
env._G = env
env.ipairs = _G.ipairs
env.loadstring = safeloadstring
env.next = _G.next
env.pairs = _G.pairs
env.pcall = _G.pcall
env.print = printwrapper
env.write = writewrapper
env.select = _G.select
env.tonumber = _G.tonumber
env.tostring = _G.tostring
env.type = _G.type
env.unpack = _G.unpack
env._VERSION = _G._VERSION
env.xpcall = _G.xpcall
env.coroutine = deepcopy(_G.coroutine)
env.string = deepcopy(_G.string)
env.string.dump = nil
env.table = deepcopy(_G.table)
env.math = deepcopy(_G.math)
env.io = {}
env.io.write = writewrapper
env.io.flush = dummy
env.io.type = typewrapper
env.io.output = outputwrapper
env.io.stdout = outputwrapper()
env.os = {}
env.os.clock = _G.os.clock
-- env.os.date = _G.os.date
env.os.difftime = _G.os.difftime
env.os.time = _G.os.time
-- Return the new sandbox environment
return env
end
-- Creates a new debug hook that aborts with 'error("LOC_LIMIT")' after
-- 'maxlines' lines have been passed, or 'error("RECURSION_LIMIT")' after
-- 'maxcalls' levels of recursion have been entered.
function make_hook(maxlines, maxcalls, diefunc)
local lines = 0
local calls = 0
function _hook(event, ...)
if event == "line" then
lines = lines + 1
if lines > maxlines then
error("LOC_LIMIT")
end
elseif event == "call" then
calls = calls + 1
if calls > maxcalls then
error("RECURSION_LIMIT")
end
elseif event == "return" then
calls = calls - 1
end
end
return _hook
end
-- Creates and returns a function, 'wrap(input)', which reads a string into
-- a Lua chunk and executes it in a persistent sandbox environment, returning
-- 'output, err' where 'output' is the combined output of print() and friends
-- from within the chunk and 'err' is either nil or an error incurred while
-- executing the chunk; or halting after 'maxlines' lines or 'maxcalls' levels
-- of recursion.
function make_wrapper(maxlines, maxcalls)
-- Create the debug hook and sandbox environment.
local hook = make_hook(maxlines, maxcalls)
local env = make_sandbox()
-- The actual 'wrap()' function.
-- All of the above variables will be bound in its closure.
function _wrap(chunkstr)
local chunk, err, done
-- Clear any leftover output from the last call
env._OUTPUT = ""
err = nil
-- Load the string into a chunk; fail on error
chunk, err = loadstring(chunkstr)
if err ~= nil then
return nil, err
end
-- Set the chunk's environment, enable the debug hook, and execute it
setfenv(chunk, env)
co = coroutine.create(chunk)
debug.sethook(co, hook, "crl")
done, err = coroutine.resume(co)
if done == true then
err = nil
end
-- Collect and return the results
return env._OUTPUT, err
end
return _wrap
end
-- Listen on stdin for Lua chunks, parse and execute them, and print the
-- results of each on stdout.
function main(arg)
if #arg ~= 2 then
io.stderr:write(string.format("usage: %s MAXLINES MAXCALLS\n", arg[0]))
os.exit(1)
end
-- Create a wrapper function, wrap()
local wrap = make_wrapper(tonumber(arg[1]), tonumber(arg[2]))
-- Turn off buffering, and loop through the input
io.stdout:setvbuf("no")
while true do
-- Read in a chunk
local chunkstr = ""
while true do
local line = io.stdin:read("*l")
if chunkstr == "" and line == nil then
-- On EOF, exit.
os.exit(0)
elseif line == "." or line == nil then
-- Finished this chunk; move on to the next step
break
elseif chunkstr ~= "" then
chunkstr = chunkstr .. "\n" .. line
else
chunkstr = line
end
end
-- Parse and execute the chunk
local res, err
res, err = wrap(chunkstr, env, hook)
-- Write out the results
if err == nil then
io.stdout:write("'", res, "', true\n.\n")
else
io.stdout:write("'", err, "', false\n.\n")
end
end
end
-- If called as a script instead of imported as a library, run main().
if arg ~= nil then
main(arg)
end
|