From 9aca31681a070ef9119e1bb4d7a60554100bc835 Mon Sep 17 00:00:00 2001 From: Brad Jorsch Date: Tue, 6 Feb 2018 16:07:11 -0500 Subject: [PATCH] LuaStandalone: Improve passing of numeric values For integers from Lua to PHP, make sure they won't use exponential notation that will confuse unserialize(), and pass the integer size from PHP so Lua can know which numbers are representable as integers. For doubles in both directions, increase the precision to avoid truncation of the least significant bits. Change-Id: Icfaff71cab0ee1aac04acf752d108049b5569380 --- engines/LuaStandalone/LuaStandaloneEngine.php | 5 +++-- engines/LuaStandalone/MWServer.lua | 22 +++++++++++++------ engines/LuaStandalone/mw_main.lua | 2 +- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/engines/LuaStandalone/LuaStandaloneEngine.php b/engines/LuaStandalone/LuaStandaloneEngine.php index 728e3c05..bfc02da9 100644 --- a/engines/LuaStandalone/LuaStandaloneEngine.php +++ b/engines/LuaStandalone/LuaStandaloneEngine.php @@ -198,7 +198,8 @@ class Scribunto_LuaStandaloneInterpreter extends Scribunto_LuaInterpreter { $options['luaPath'], __DIR__ . '/mw_main.lua', dirname( dirname( __DIR__ ) ), - $this->id + $this->id, + PHP_INT_SIZE ); if ( php_uname( 's' ) == 'Linux' ) { // Limit memory and CPU @@ -560,7 +561,7 @@ class Scribunto_LuaStandaloneInterpreter extends Scribunto_LuaInterpreter { } throw new MWException( __METHOD__.': cannot convert non-finite number' ); } - return $var; + return sprintf( '%.17g', $var ); case 'string': return '"' . strtr( $var, [ diff --git a/engines/LuaStandalone/MWServer.lua b/engines/LuaStandalone/MWServer.lua index c4d9fcf8..de4af3b1 100644 --- a/engines/LuaStandalone/MWServer.lua +++ b/engines/LuaStandalone/MWServer.lua @@ -1,11 +1,15 @@ MWServer = {} --- Create a new MWServer object -function MWServer:new( interpreterId ) +function MWServer:new( interpreterId, intSize ) interpreterId = tonumber( interpreterId ) if not interpreterId then error( "bad argument #1 to 'MWServer:new' (must be a number or convertible to a number)", 2 ) end + intSize = tonumber( intSize ) + if intSize ~= 4 and intSize ~= 8 then + error( "bad argument #2 to 'MWServer:new' (must be 4 or 8)", 2 ) + end obj = { interpreterId = interpreterId, @@ -16,6 +20,12 @@ function MWServer:new( interpreterId ) protectedEnvironments = {}, baseEnv = {} } + if intSize == 4 then + obj.intMax = 2147483648 + else + -- Lua can't represent most larger integers, so they may as well be sent to PHP as floats. + obj.intMax = 9007199254740992 + end setmetatable( obj, self ) self.__index = self @@ -457,14 +467,12 @@ local serialize_replacements = { -- @param var The value. 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 + and var >= -self.intMax + and var < self.intMax end local function recursiveEncode( var, level ) @@ -473,9 +481,9 @@ function MWServer:serialize( var ) return 'N;' elseif t == 'number' then if isInteger(var) then - return 'i:' .. var .. ';' + return 'i:' .. string.format( '%d', var ) .. ';' elseif var < math.huge and var > -math.huge then - return 'd:' .. var .. ';' + return 'd:' .. string.format( '%.17g', var ) .. ';' elseif var == math.huge then return 'd:INF;' elseif var == -math.huge then diff --git a/engines/LuaStandalone/mw_main.lua b/engines/LuaStandalone/mw_main.lua index c8198a2d..651ab751 100644 --- a/engines/LuaStandalone/mw_main.lua +++ b/engines/LuaStandalone/mw_main.lua @@ -3,6 +3,6 @@ package.path = arg[1] .. '/engines/LuaStandalone/?.lua;' .. require('MWServer') require('mwInit') -server = MWServer:new( arg[2] ) +server = MWServer:new( arg[2], arg[3] ) server:execute()