2012-04-13 10:38:12 +00:00
|
|
|
MWServer = {}
|
|
|
|
|
|
|
|
function MWServer:new()
|
|
|
|
obj = {
|
|
|
|
chunks = {},
|
|
|
|
xchunks = {},
|
|
|
|
protectedFunctions = {},
|
|
|
|
baseEnv = {}
|
|
|
|
}
|
|
|
|
setmetatable( obj, self )
|
|
|
|
self.__index = self
|
|
|
|
|
|
|
|
obj:init()
|
|
|
|
|
|
|
|
return obj
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:init()
|
|
|
|
self.baseEnv = self:newEnvironment()
|
|
|
|
for funcName, func in pairs( self ) do
|
|
|
|
if type(func) == 'function' then
|
|
|
|
self.protectedFunctions[func] = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:execute()
|
|
|
|
self:dispatch( nil )
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:call( id, args )
|
|
|
|
local result = self:dispatch( {
|
|
|
|
op = 'call',
|
|
|
|
id = id,
|
|
|
|
args = args
|
|
|
|
} )
|
|
|
|
if result.op == 'return' then
|
Added tests and fixed bugs
* Added unit tests for the two Lua interpreter classes
* Fixed a bug in checkType()
* Have Scribunto_LuaSandboxInterpreter throw an exception on construct
when the extension doesn't exist, to match the standalone behaviour.
* In Scribunto_LuaSandboxInterpreter, removed debugging statements
accidentally left in.
* Convert LuaSandboxTimeoutError to the appropriate common error
message.
* Moved the option munging from the sandbox engine to the interpreter,
so that the interpreter can be unit tested separately.
* Use /bin/sh instead of bash for lua_ulimit.sh, since dash is smaller
and still supports ulimit.
* Use exec to run the lua binary, so that the vsize of the shell doesn't
add to the memory limit.
* Added a quit function to the standalone interpreter. Unused at present.
* Don't add a comma after the last element of a table in a Lua
expression.
* Make the SIGXCPU detection work: proc_open() runs the command via a
shell, which reports signals in the child via the exit status, so
proc_get_status() will never return a valid termsig element.
* In MWServer:call(), fixed a bug causing the return values to be
wrapped in an array.
* Fixed a misunderstanding of what select() does.
* In MWServer:getStatus(), fixed indexes so that vsize will be correct.
Removed RSS, since it wasn't used anyway and turns out to be measured
in multiples of the page size, and I couldn't be bothered trying to
fetch that from getconf. Return the PID and vsize as numbers rather
than strings.
* Added a simple table dump feature to MWServer:debug().
* Fixed brackets in MWServer:tostring().
* Added missing Linux 32-bit binary.
Change-Id: Ibf5f4656b1c0a9f81287d363184c3fe9d2abdafd
2012-04-16 04:41:08 +00:00
|
|
|
return unpack( result.values )
|
2012-04-13 10:38:12 +00:00
|
|
|
elseif result.op == 'error' then
|
|
|
|
-- Raise an error in the actual user code that called the function
|
|
|
|
-- The level is 3 since our immediate caller is a closure
|
|
|
|
error( result.value, 3 )
|
|
|
|
else
|
|
|
|
error( 'MWServer:call: unexpected result op' )
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:handleCall( message )
|
|
|
|
local result = { pcall( self.chunks[message.id], unpack( message.args ) ) }
|
|
|
|
if (result[1]) then
|
|
|
|
table.remove( result, 1 )
|
|
|
|
return {
|
|
|
|
op = 'return',
|
|
|
|
values = result
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return {
|
|
|
|
op = 'error',
|
|
|
|
value = result[2]
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:handleLoadString( message )
|
|
|
|
if string.find( message.text, '\27Lua', 1, true ) then
|
|
|
|
return {
|
|
|
|
op = 'error',
|
|
|
|
value = 'cannot load code with a Lua binary chunk marker escape sequence in it'
|
|
|
|
}
|
|
|
|
end
|
|
|
|
local chunk, errorMsg = loadstring( message.text, message.chunkName )
|
|
|
|
if chunk then
|
|
|
|
setfenv( chunk, self.baseEnv )
|
|
|
|
local id = self:addChunk( chunk )
|
|
|
|
return {
|
|
|
|
op = 'return',
|
|
|
|
values = {id}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return {
|
|
|
|
op = 'error',
|
|
|
|
value = errorMsg
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:addChunk( chunk )
|
|
|
|
local id = #self.chunks + 1
|
|
|
|
self.chunks[id] = chunk
|
|
|
|
self.xchunks[chunk] = id
|
|
|
|
return id
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:handleRegisterLibrary( message )
|
|
|
|
local startPos = 1
|
|
|
|
local component
|
|
|
|
local t = self.baseEnv
|
|
|
|
while startPos <= #message.name do
|
|
|
|
local dotPos = string.find( message.name, '.', startPos, true )
|
|
|
|
if not dotPos then
|
|
|
|
dotPos = #message.name + 1
|
|
|
|
end
|
|
|
|
component = string.sub( message.name, startPos, dotPos - 1 )
|
|
|
|
if t[component] == nil then
|
|
|
|
t[component] = {}
|
|
|
|
end
|
|
|
|
t = t[component]
|
|
|
|
startPos = dotPos + 1
|
|
|
|
end
|
|
|
|
|
|
|
|
for name, id in pairs( message.functions ) do
|
Added tests and fixed bugs
* Added unit tests for the two Lua interpreter classes
* Fixed a bug in checkType()
* Have Scribunto_LuaSandboxInterpreter throw an exception on construct
when the extension doesn't exist, to match the standalone behaviour.
* In Scribunto_LuaSandboxInterpreter, removed debugging statements
accidentally left in.
* Convert LuaSandboxTimeoutError to the appropriate common error
message.
* Moved the option munging from the sandbox engine to the interpreter,
so that the interpreter can be unit tested separately.
* Use /bin/sh instead of bash for lua_ulimit.sh, since dash is smaller
and still supports ulimit.
* Use exec to run the lua binary, so that the vsize of the shell doesn't
add to the memory limit.
* Added a quit function to the standalone interpreter. Unused at present.
* Don't add a comma after the last element of a table in a Lua
expression.
* Make the SIGXCPU detection work: proc_open() runs the command via a
shell, which reports signals in the child via the exit status, so
proc_get_status() will never return a valid termsig element.
* In MWServer:call(), fixed a bug causing the return values to be
wrapped in an array.
* Fixed a misunderstanding of what select() does.
* In MWServer:getStatus(), fixed indexes so that vsize will be correct.
Removed RSS, since it wasn't used anyway and turns out to be measured
in multiples of the page size, and I couldn't be bothered trying to
fetch that from getconf. Return the PID and vsize as numbers rather
than strings.
* Added a simple table dump feature to MWServer:debug().
* Fixed brackets in MWServer:tostring().
* Added missing Linux 32-bit binary.
Change-Id: Ibf5f4656b1c0a9f81287d363184c3fe9d2abdafd
2012-04-16 04:41:08 +00:00
|
|
|
t[name] = function( ... )
|
|
|
|
return self:call( id, { ... } )
|
2012-04-13 10:38:12 +00:00
|
|
|
end
|
|
|
|
-- Protect the function against setfenv()
|
|
|
|
self.protectedFunctions[t[name]] = true
|
|
|
|
end
|
|
|
|
|
|
|
|
return {
|
|
|
|
op = 'return',
|
|
|
|
values = {}
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:handleGetStatus( message )
|
|
|
|
local nullRet = {
|
|
|
|
op = 'return',
|
|
|
|
values = {}
|
|
|
|
}
|
|
|
|
local file = io.open( '/proc/self/stat' )
|
|
|
|
if not file then
|
|
|
|
return nullRet
|
|
|
|
end
|
|
|
|
local s = file:read('*a')
|
|
|
|
file:close()
|
|
|
|
local t = {}
|
|
|
|
for token in string.gmatch(s, '[^ ]+') do
|
|
|
|
t[#t + 1] = token
|
|
|
|
end
|
Added tests and fixed bugs
* Added unit tests for the two Lua interpreter classes
* Fixed a bug in checkType()
* Have Scribunto_LuaSandboxInterpreter throw an exception on construct
when the extension doesn't exist, to match the standalone behaviour.
* In Scribunto_LuaSandboxInterpreter, removed debugging statements
accidentally left in.
* Convert LuaSandboxTimeoutError to the appropriate common error
message.
* Moved the option munging from the sandbox engine to the interpreter,
so that the interpreter can be unit tested separately.
* Use /bin/sh instead of bash for lua_ulimit.sh, since dash is smaller
and still supports ulimit.
* Use exec to run the lua binary, so that the vsize of the shell doesn't
add to the memory limit.
* Added a quit function to the standalone interpreter. Unused at present.
* Don't add a comma after the last element of a table in a Lua
expression.
* Make the SIGXCPU detection work: proc_open() runs the command via a
shell, which reports signals in the child via the exit status, so
proc_get_status() will never return a valid termsig element.
* In MWServer:call(), fixed a bug causing the return values to be
wrapped in an array.
* Fixed a misunderstanding of what select() does.
* In MWServer:getStatus(), fixed indexes so that vsize will be correct.
Removed RSS, since it wasn't used anyway and turns out to be measured
in multiples of the page size, and I couldn't be bothered trying to
fetch that from getconf. Return the PID and vsize as numbers rather
than strings.
* Added a simple table dump feature to MWServer:debug().
* Fixed brackets in MWServer:tostring().
* Added missing Linux 32-bit binary.
Change-Id: Ibf5f4656b1c0a9f81287d363184c3fe9d2abdafd
2012-04-16 04:41:08 +00:00
|
|
|
if #t < 22 then
|
2012-04-13 10:38:12 +00:00
|
|
|
return nullRet
|
|
|
|
end
|
|
|
|
return {
|
|
|
|
op = 'return',
|
|
|
|
values = {{
|
Added tests and fixed bugs
* Added unit tests for the two Lua interpreter classes
* Fixed a bug in checkType()
* Have Scribunto_LuaSandboxInterpreter throw an exception on construct
when the extension doesn't exist, to match the standalone behaviour.
* In Scribunto_LuaSandboxInterpreter, removed debugging statements
accidentally left in.
* Convert LuaSandboxTimeoutError to the appropriate common error
message.
* Moved the option munging from the sandbox engine to the interpreter,
so that the interpreter can be unit tested separately.
* Use /bin/sh instead of bash for lua_ulimit.sh, since dash is smaller
and still supports ulimit.
* Use exec to run the lua binary, so that the vsize of the shell doesn't
add to the memory limit.
* Added a quit function to the standalone interpreter. Unused at present.
* Don't add a comma after the last element of a table in a Lua
expression.
* Make the SIGXCPU detection work: proc_open() runs the command via a
shell, which reports signals in the child via the exit status, so
proc_get_status() will never return a valid termsig element.
* In MWServer:call(), fixed a bug causing the return values to be
wrapped in an array.
* Fixed a misunderstanding of what select() does.
* In MWServer:getStatus(), fixed indexes so that vsize will be correct.
Removed RSS, since it wasn't used anyway and turns out to be measured
in multiples of the page size, and I couldn't be bothered trying to
fetch that from getconf. Return the PID and vsize as numbers rather
than strings.
* Added a simple table dump feature to MWServer:debug().
* Fixed brackets in MWServer:tostring().
* Added missing Linux 32-bit binary.
Change-Id: Ibf5f4656b1c0a9f81287d363184c3fe9d2abdafd
2012-04-16 04:41:08 +00:00
|
|
|
pid = tonumber(t[1]),
|
2012-04-13 10:38:12 +00:00
|
|
|
time = tonumber(t[14]) + tonumber(t[15]) + tonumber(t[16]) + tonumber(t[17]),
|
Added tests and fixed bugs
* Added unit tests for the two Lua interpreter classes
* Fixed a bug in checkType()
* Have Scribunto_LuaSandboxInterpreter throw an exception on construct
when the extension doesn't exist, to match the standalone behaviour.
* In Scribunto_LuaSandboxInterpreter, removed debugging statements
accidentally left in.
* Convert LuaSandboxTimeoutError to the appropriate common error
message.
* Moved the option munging from the sandbox engine to the interpreter,
so that the interpreter can be unit tested separately.
* Use /bin/sh instead of bash for lua_ulimit.sh, since dash is smaller
and still supports ulimit.
* Use exec to run the lua binary, so that the vsize of the shell doesn't
add to the memory limit.
* Added a quit function to the standalone interpreter. Unused at present.
* Don't add a comma after the last element of a table in a Lua
expression.
* Make the SIGXCPU detection work: proc_open() runs the command via a
shell, which reports signals in the child via the exit status, so
proc_get_status() will never return a valid termsig element.
* In MWServer:call(), fixed a bug causing the return values to be
wrapped in an array.
* Fixed a misunderstanding of what select() does.
* In MWServer:getStatus(), fixed indexes so that vsize will be correct.
Removed RSS, since it wasn't used anyway and turns out to be measured
in multiples of the page size, and I couldn't be bothered trying to
fetch that from getconf. Return the PID and vsize as numbers rather
than strings.
* Added a simple table dump feature to MWServer:debug().
* Fixed brackets in MWServer:tostring().
* Added missing Linux 32-bit binary.
Change-Id: Ibf5f4656b1c0a9f81287d363184c3fe9d2abdafd
2012-04-16 04:41:08 +00:00
|
|
|
vsize = tonumber(t[23]),
|
2012-04-13 10:38:12 +00:00
|
|
|
}}
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:dispatch( msgToPhp )
|
|
|
|
if msgToPhp then
|
|
|
|
self:sendMessage( msgToPhp )
|
|
|
|
end
|
|
|
|
while true do
|
|
|
|
local msgFromPhp = self:receiveMessage()
|
|
|
|
local msgToPhp
|
|
|
|
local op = msgFromPhp.op
|
|
|
|
if op == 'return' or op == 'error' then
|
|
|
|
return msgFromPhp
|
|
|
|
elseif op == 'call' then
|
|
|
|
msgToPhp = self:handleCall( msgFromPhp )
|
|
|
|
self:sendMessage( msgToPhp )
|
|
|
|
elseif op == 'loadString' then
|
|
|
|
msgToPhp = self:handleLoadString( msgFromPhp )
|
|
|
|
self:sendMessage( msgToPhp )
|
|
|
|
elseif op == 'registerLibrary' then
|
|
|
|
msgToPhp = self:handleRegisterLibrary( msgFromPhp )
|
|
|
|
self:sendMessage( msgToPhp )
|
|
|
|
elseif op == 'getStatus' then
|
|
|
|
msgToPhp = self:handleGetStatus( msgFromPhp )
|
|
|
|
self:sendMessage( msgToPhp )
|
Added tests and fixed bugs
* Added unit tests for the two Lua interpreter classes
* Fixed a bug in checkType()
* Have Scribunto_LuaSandboxInterpreter throw an exception on construct
when the extension doesn't exist, to match the standalone behaviour.
* In Scribunto_LuaSandboxInterpreter, removed debugging statements
accidentally left in.
* Convert LuaSandboxTimeoutError to the appropriate common error
message.
* Moved the option munging from the sandbox engine to the interpreter,
so that the interpreter can be unit tested separately.
* Use /bin/sh instead of bash for lua_ulimit.sh, since dash is smaller
and still supports ulimit.
* Use exec to run the lua binary, so that the vsize of the shell doesn't
add to the memory limit.
* Added a quit function to the standalone interpreter. Unused at present.
* Don't add a comma after the last element of a table in a Lua
expression.
* Make the SIGXCPU detection work: proc_open() runs the command via a
shell, which reports signals in the child via the exit status, so
proc_get_status() will never return a valid termsig element.
* In MWServer:call(), fixed a bug causing the return values to be
wrapped in an array.
* Fixed a misunderstanding of what select() does.
* In MWServer:getStatus(), fixed indexes so that vsize will be correct.
Removed RSS, since it wasn't used anyway and turns out to be measured
in multiples of the page size, and I couldn't be bothered trying to
fetch that from getconf. Return the PID and vsize as numbers rather
than strings.
* Added a simple table dump feature to MWServer:debug().
* Fixed brackets in MWServer:tostring().
* Added missing Linux 32-bit binary.
Change-Id: Ibf5f4656b1c0a9f81287d363184c3fe9d2abdafd
2012-04-16 04:41:08 +00:00
|
|
|
elseif op == 'quit' then
|
|
|
|
os.exit(0)
|
2012-04-13 10:38:12 +00:00
|
|
|
else
|
|
|
|
error( "Invalid message operation" )
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:debug( s )
|
Added tests and fixed bugs
* Added unit tests for the two Lua interpreter classes
* Fixed a bug in checkType()
* Have Scribunto_LuaSandboxInterpreter throw an exception on construct
when the extension doesn't exist, to match the standalone behaviour.
* In Scribunto_LuaSandboxInterpreter, removed debugging statements
accidentally left in.
* Convert LuaSandboxTimeoutError to the appropriate common error
message.
* Moved the option munging from the sandbox engine to the interpreter,
so that the interpreter can be unit tested separately.
* Use /bin/sh instead of bash for lua_ulimit.sh, since dash is smaller
and still supports ulimit.
* Use exec to run the lua binary, so that the vsize of the shell doesn't
add to the memory limit.
* Added a quit function to the standalone interpreter. Unused at present.
* Don't add a comma after the last element of a table in a Lua
expression.
* Make the SIGXCPU detection work: proc_open() runs the command via a
shell, which reports signals in the child via the exit status, so
proc_get_status() will never return a valid termsig element.
* In MWServer:call(), fixed a bug causing the return values to be
wrapped in an array.
* Fixed a misunderstanding of what select() does.
* In MWServer:getStatus(), fixed indexes so that vsize will be correct.
Removed RSS, since it wasn't used anyway and turns out to be measured
in multiples of the page size, and I couldn't be bothered trying to
fetch that from getconf. Return the PID and vsize as numbers rather
than strings.
* Added a simple table dump feature to MWServer:debug().
* Fixed brackets in MWServer:tostring().
* Added missing Linux 32-bit binary.
Change-Id: Ibf5f4656b1c0a9f81287d363184c3fe9d2abdafd
2012-04-16 04:41:08 +00:00
|
|
|
if ( type(s) == 'string' ) then
|
|
|
|
io.stderr:write( s .. '\n' )
|
|
|
|
else
|
|
|
|
io.stderr:write( self:serialize( s ) .. '\n' )
|
|
|
|
end
|
2012-04-13 10:38:12 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:ioError( header, info )
|
|
|
|
if type( info) == 'string' then
|
|
|
|
error( header .. ': ' .. info, 2 )
|
|
|
|
else
|
|
|
|
error( header, 2 )
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:sendMessage( msg )
|
|
|
|
if not msg.op then
|
|
|
|
error( "MWServer:sendMessage: invalid message", 2 )
|
|
|
|
end
|
|
|
|
self:debug('==> ' .. msg.op)
|
|
|
|
local encMsg = self:encodeMessage( msg )
|
|
|
|
local success, errorMsg = io.stdout:write( encMsg )
|
|
|
|
if not success then
|
|
|
|
self:ioError( 'Write error', errorMsg )
|
|
|
|
end
|
|
|
|
io.stdout:flush()
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:receiveMessage()
|
|
|
|
-- Read the header
|
|
|
|
local header, errorMsg = io.stdin:read( 16 )
|
|
|
|
if header == nil and errorMsg == nil then
|
|
|
|
-- End of file on stdin, exit gracefully
|
|
|
|
os.exit(0)
|
|
|
|
end
|
|
|
|
|
|
|
|
if not header or #header ~= 16 then
|
|
|
|
self:ioError( 'Read error', errorMsg )
|
|
|
|
end
|
|
|
|
local length = self:decodeHeader( header )
|
|
|
|
|
|
|
|
-- Read the body
|
|
|
|
local body, errorMsg = io.stdin:read( length )
|
|
|
|
if not body then
|
|
|
|
self:ioError( 'Read error', errorMsg )
|
|
|
|
end
|
|
|
|
if #body ~= length then
|
|
|
|
self:ioError( 'Read error', errorMsg )
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Unserialize it
|
|
|
|
msg = self:unserialize( body )
|
|
|
|
self:debug('<== ' .. msg.op)
|
|
|
|
return msg
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:encodeMessage( message )
|
|
|
|
local serialized = self:serialize( message )
|
|
|
|
local length = #serialized
|
|
|
|
local check = length * 2 - 1
|
|
|
|
return string.format( '%08x%08x%s', length, check, serialized )
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:serialize( var )
|
|
|
|
local done = {}
|
|
|
|
local int_min = -2147483648
|
|
|
|
local int_max = 2147483647
|
|
|
|
|
|
|
|
local function isInteger( var )
|
|
|
|
return type(var) == 'number'
|
|
|
|
and math.floor( var ) == var
|
|
|
|
and var >= int_min
|
|
|
|
and var <= int_max
|
|
|
|
end
|
|
|
|
|
|
|
|
local function recursiveEncode( var, level )
|
|
|
|
local t = type( var )
|
|
|
|
if t == 'nil' then
|
|
|
|
return 'N;'
|
|
|
|
elseif t == 'number' then
|
|
|
|
if isInteger(var) then
|
|
|
|
return 'i:' .. var .. ';'
|
|
|
|
else
|
|
|
|
return 'd:' .. var .. ';'
|
|
|
|
end
|
|
|
|
elseif t == 'string' then
|
|
|
|
return 's:' .. string.len( var ) .. ':"' .. var .. '";'
|
|
|
|
elseif t == 'boolean' then
|
|
|
|
if var then
|
|
|
|
return 'b:1;'
|
|
|
|
else
|
|
|
|
return 'b:0;'
|
|
|
|
end
|
|
|
|
elseif t == 'table' then
|
|
|
|
if done[var] then
|
|
|
|
error("Cannot pass circular reference to PHP")
|
|
|
|
end
|
|
|
|
done[var] = true
|
|
|
|
local buf = { '' }
|
|
|
|
local tmpString
|
|
|
|
local numElements = 0
|
|
|
|
for key, value in pairs(var) do
|
|
|
|
if (isInteger(key)) then
|
|
|
|
buf[#buf + 1] = 'i:' .. key .. ';'
|
|
|
|
else
|
|
|
|
tmpString = tostring( key )
|
|
|
|
buf[#buf + 1] = recursiveEncode( tostring( key ), level + 1 )
|
|
|
|
end
|
|
|
|
buf[#buf + 1] = recursiveEncode( value, level + 1 )
|
|
|
|
numElements = numElements + 1
|
|
|
|
end
|
|
|
|
buf[1] = 'a:' .. numElements .. ':{'
|
|
|
|
buf[#buf + 1] = '}'
|
|
|
|
return table.concat(buf)
|
|
|
|
elseif t == 'function' then
|
|
|
|
local id
|
|
|
|
if self.xchunks[var] then
|
|
|
|
id = self.xchunks[var]
|
|
|
|
else
|
|
|
|
id = self:addChunk(var)
|
|
|
|
end
|
|
|
|
return 'O:42:"Scribunto_LuaStandaloneInterpreterFunction":1:{s:2:"id";i:' .. id .. ';}'
|
|
|
|
elseif t == 'thread' then
|
|
|
|
error("Cannot pass thread to PHP")
|
|
|
|
elseif t == 'userdata' then
|
|
|
|
error("Cannot pass userdata to PHP")
|
|
|
|
else
|
|
|
|
error("Cannot pass unrecognised type to PHP")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return recursiveEncode( var, 0 )
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:unserialize( text )
|
|
|
|
local func = loadstring( 'return ' .. text )
|
|
|
|
-- Don't waste JIT cache space by storing every message in it
|
|
|
|
if jit then
|
|
|
|
jit.off( func )
|
|
|
|
end
|
|
|
|
setfenv( func, { chunks = self.chunks } )
|
|
|
|
return func()
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:decodeHeader( header )
|
|
|
|
local length = string.sub( header, 1, 8 )
|
|
|
|
local check = string.sub( header, 9, 16 )
|
|
|
|
if not string.match( length, '^%x+$' ) or not string.match( check, '^%x+$' ) then
|
|
|
|
error( "Error decoding message header: " .. length .. '/' .. check )
|
|
|
|
end
|
|
|
|
length = tonumber( length, 16 )
|
|
|
|
check = tonumber( check, 16 )
|
|
|
|
if length * 2 - 1 ~= check then
|
|
|
|
error( "Error decoding message header" )
|
|
|
|
end
|
|
|
|
return length
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:clone( val )
|
|
|
|
local tableRefs = {}
|
|
|
|
local function recursiveClone( val )
|
|
|
|
if type( val ) == 'table' then
|
|
|
|
-- Encode circular references correctly
|
|
|
|
if tableRefs[val] ~= nil then
|
|
|
|
return tableRefs[val]
|
|
|
|
end
|
|
|
|
|
|
|
|
local retVal
|
|
|
|
retVal = {}
|
|
|
|
tableRefs[val] = retVal
|
|
|
|
for key, elt in pairs( val ) do
|
|
|
|
retVal[key] = recursiveClone( elt )
|
|
|
|
end
|
|
|
|
return retVal
|
|
|
|
else
|
|
|
|
return val
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return recursiveClone( val )
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:newEnvironment()
|
|
|
|
local allowedGlobals = {
|
|
|
|
-- base
|
|
|
|
"assert",
|
|
|
|
"error",
|
|
|
|
"getmetatable",
|
|
|
|
"getmetatable",
|
|
|
|
"ipairs",
|
|
|
|
"next",
|
|
|
|
"pairs",
|
|
|
|
"pcall",
|
|
|
|
"rawequal",
|
|
|
|
"rawget",
|
|
|
|
"rawset",
|
|
|
|
"select",
|
|
|
|
"setmetatable",
|
|
|
|
"tonumber",
|
|
|
|
"type",
|
|
|
|
"unpack",
|
|
|
|
"xpcall",
|
|
|
|
"_VERSION",
|
|
|
|
-- libs
|
|
|
|
"string",
|
|
|
|
"table",
|
|
|
|
"math"
|
|
|
|
}
|
|
|
|
|
|
|
|
local env = {}
|
|
|
|
local i
|
|
|
|
for i = 1, #allowedGlobals do
|
|
|
|
env[allowedGlobals[i]] = self:clone( _G[allowedGlobals[i]] )
|
|
|
|
end
|
|
|
|
|
|
|
|
env._G = env
|
|
|
|
env.tostring = function( val )
|
|
|
|
self:tostring( val )
|
|
|
|
end
|
|
|
|
env.string.dump = nil
|
|
|
|
env.setfenv = function( func, newEnv )
|
|
|
|
self:setfenv( func, newEnv )
|
|
|
|
end
|
|
|
|
return env
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:tostring(val)
|
|
|
|
local mt = getmetatable( val )
|
|
|
|
if mt and mt.__tostring then
|
|
|
|
return mt.__tostring(val)
|
|
|
|
end
|
|
|
|
local typeName = type(val)
|
|
|
|
local nonPointerTypes = {number = true, string = true, boolean = true, ['nil'] = true}
|
Added tests and fixed bugs
* Added unit tests for the two Lua interpreter classes
* Fixed a bug in checkType()
* Have Scribunto_LuaSandboxInterpreter throw an exception on construct
when the extension doesn't exist, to match the standalone behaviour.
* In Scribunto_LuaSandboxInterpreter, removed debugging statements
accidentally left in.
* Convert LuaSandboxTimeoutError to the appropriate common error
message.
* Moved the option munging from the sandbox engine to the interpreter,
so that the interpreter can be unit tested separately.
* Use /bin/sh instead of bash for lua_ulimit.sh, since dash is smaller
and still supports ulimit.
* Use exec to run the lua binary, so that the vsize of the shell doesn't
add to the memory limit.
* Added a quit function to the standalone interpreter. Unused at present.
* Don't add a comma after the last element of a table in a Lua
expression.
* Make the SIGXCPU detection work: proc_open() runs the command via a
shell, which reports signals in the child via the exit status, so
proc_get_status() will never return a valid termsig element.
* In MWServer:call(), fixed a bug causing the return values to be
wrapped in an array.
* Fixed a misunderstanding of what select() does.
* In MWServer:getStatus(), fixed indexes so that vsize will be correct.
Removed RSS, since it wasn't used anyway and turns out to be measured
in multiples of the page size, and I couldn't be bothered trying to
fetch that from getconf. Return the PID and vsize as numbers rather
than strings.
* Added a simple table dump feature to MWServer:debug().
* Fixed brackets in MWServer:tostring().
* Added missing Linux 32-bit binary.
Change-Id: Ibf5f4656b1c0a9f81287d363184c3fe9d2abdafd
2012-04-16 04:41:08 +00:00
|
|
|
if nonPointerTypes[typeName] then
|
2012-04-13 10:38:12 +00:00
|
|
|
return tostring(val)
|
|
|
|
else
|
|
|
|
return typeName
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function MWServer:setfenv( func, newEnv )
|
|
|
|
if type( func ) ~= 'function' then
|
|
|
|
error( "'setfenv' can only be called with a function as the first argument" )
|
|
|
|
end
|
|
|
|
if self.protectedFunctions[func] then
|
|
|
|
error( "'setfenv' cannot be called on a protected function" )
|
|
|
|
end
|
|
|
|
setfenv( func, newEnv )
|
|
|
|
return func
|
|
|
|
end
|
|
|
|
|
|
|
|
return MWServer
|