Skip to content

[fork-ffi] integers: shl / shr / zshr — All three use math.pow/division and do not implement JS 32-bit… #91

@Unisay

Description

@Unisay

Package: purescript-lua-integers
File: src/Data/Int/Bits.lua
Function: shl / shr / zshr
Class: semantics Severity: medium

All three use math.pow/division and do not implement JS 32-bit shift semantics. (1) shl: a * math.pow(2, b) returns a float and is neither masked to a 5-bit shift count nor wrapped to Int32, so shl 1 31 gives 2147483648.0 (JS 1 << 31 == -2147483648) and shl 1 32 gives 4294967296 (JS 1 << 32 == 1, count taken mod 32). (2) zshr is identical to shr (math.floor(a / 2^b)), but JS >>> is the UNSIGNED right shift: zshr (-8) 1 must be 2147483644, while the Lua returns -4. (3) shr on negative a happens to match arithmetic shift for the cases tried, but neither masks the shift count nor stays in Int32.

Current (Lua):

shl = (function(a) return function(b) return a * math.pow(2, b) end end),
shr = (function(a) return function(b) return math.floor(a / math.pow(2, b)) end end),
zshr = (function(a) return function(b) return math.floor(a / math.pow(2, b)) end end),

Expected: JS 32-bit shifts: shift count taken mod 32, result wrapped to signed Int32 for shl/shr; zshr operates on the unsigned 32-bit value (zshr (-8) 1 == 2147483644). shl 1 31 == -2147483648, shl 1 32 == 1.

Proposed fix:

Implement via an unsigned-32-bit helper: for shl, compute `(a * 2^(b % 32)) % 0x100000000` then reinterpret as signed Int32; for zshr, first map a to unsigned (a + 0x100000000 if a < 0) then `math.floor(u / 2^(b % 32))`; for shr, do an arithmetic shift on the signed value with count masked to 5 bits. A shared signed/unsigned-32 conversion pair removes the duplication.

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