Package: purescript-lua-integers
File: src/Data/Int.lua
Function: fromStringAsImpl
Class: semantics Severity: high
Two divergences from the upstream JS (which validates with a base-specific regex and then checks (i | 0) === i). (1) Lua tonumber(s, radix) accepts fractional strings and out-of-range integers: tonumber("0.1",10) -> 0.1 and tonumber("2147483648",10) -> 2147483648, so fromString "0.1" returns Just 0.1 and fromString "2147483648" returns Just 2147483648, whereas the tests require Nothing for both (Test/Data/Int.purs lines 73-78). (2) For any base other than 10, Lua 5.1 tonumber treats a leading '-' as an UNSIGNED 64-bit wraparound rather than a negation: tonumber("-ef",16) -> 1.84e19 and tonumber("-80000000",16) -> 1.84e19. The tests require fromStringAs hexadecimal "-ef" == Just (-239) and fromStringAs hexadecimal "-80000000" == Just (-2147483648) (lines 91, 93); the Lua returns a huge bogus positive Just.
Current (Lua):
fromStringAsImpl = (function(just)
return function(nothing)
return function(radix)
return function(s)
local n = tonumber(s, radix)
if n == nil then return nothing end
return just(n)
end
end
end
end),
Expected: Reject non-integer strings and out-of-Int32-range values (return Nothing); parse a leading '+' or '-' sign correctly in every base, so fromStringAs hexadecimal "-ef" == Just (-239) and fromStringAs hexadecimal "-80000000" == Just (-2147483648).
Proposed fix:
return function(s)
local sign, body = 1, s
local c = s:sub(1,1)
if c == '-' then sign, body = -1, s:sub(2)
elseif c == '+' then body = s:sub(2) end
local n = tonumber(body, radix)
if n == nil then return nothing end
-- reject fractional results from base-10 parses
if math.modf(n) ~= n then return nothing end
n = sign * n
if n < -2147483648 or n > 2147483647 then return nothing end
return just(n)
end
-- (Also validate that every digit is legal for the base, mirroring the JS regex, since tonumber tolerates surrounding whitespace; trim/validate s before parsing.)
Found by the FFI audit; reproduced under Lua 5.1.
Package: purescript-lua-integers
File:
src/Data/Int.luaFunction:
fromStringAsImplClass: semantics Severity: high
Two divergences from the upstream JS (which validates with a base-specific regex and then checks
(i | 0) === i). (1) Luatonumber(s, radix)accepts fractional strings and out-of-range integers:tonumber("0.1",10)-> 0.1 andtonumber("2147483648",10)-> 2147483648, sofromString "0.1"returns Just 0.1 andfromString "2147483648"returns Just 2147483648, whereas the tests require Nothing for both (Test/Data/Int.purs lines 73-78). (2) For any base other than 10, Lua 5.1tonumbertreats a leading '-' as an UNSIGNED 64-bit wraparound rather than a negation:tonumber("-ef",16)-> 1.84e19 andtonumber("-80000000",16)-> 1.84e19. The tests requirefromStringAs hexadecimal "-ef" == Just (-239)andfromStringAs hexadecimal "-80000000" == Just (-2147483648)(lines 91, 93); the Lua returns a huge bogus positive Just.Current (Lua):
Expected: Reject non-integer strings and out-of-Int32-range values (return Nothing); parse a leading '+' or '-' sign correctly in every base, so
fromStringAs hexadecimal "-ef" == Just (-239)andfromStringAs hexadecimal "-80000000" == Just (-2147483648).Proposed fix:
Found by the FFI audit; reproduced under Lua 5.1.