Skip to content

[fork-ffi] integers: fromStringAsImpl — Two divergences from the upstream JS (which validates with a… #86

@Unisay

Description

@Unisay

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions