-
Notifications
You must be signed in to change notification settings - Fork 74
Description
Summary:
A regression has been identified in the bit32 library implementation within Tabletop Simulator. Currently, library functions (such as band, bxor, and rshift) fail to correctly process arguments when their values exceed the signed 32-bit integer range (0x7FFFFFFF / 2,147,483,647). While the library remains capable of generating correct 32-bit unsigned values, it cannot accept them back as input parameters. This behavior breaks standard bitwise logic and community scripts that previously functioned correctly.
Technical Context:
Standard bitwise libraries are expected to operate on unsigned 32-bit integers:
- All functions should operate on values within the range [0, 2^32−1].
- Arguments should be normalized via modulo 2^32 to ensure they fall within the unsigned 32-bit range.
- The result of a bitwise NOT on zero (bit32.bnot(0)) should be 0xFFFFFFFF (4294967295).
Technical Analysis:
The observed behavior suggests a regression in the Marshalling layer between the scripting VM and the host application. It appears that bit32 function arguments are now being incorrectly cast to signed int32 instead of uint32 or long before being processed by the underlying API. Consequently, any number with the 31st bit (MSB) set is treated as an invalid input or overflow, resulting in a return value of 0.
Diagnostic Test Suite:
The following suite was executed to demonstrate the internal inconsistency of the library:
-- Diagnostic Suite
local ALL_ONES = 0xFFFFFFFF -- 4294967295
local MSB_ONLY = 0x80000000 -- 2147483648
local bnot_zero = bit32.bnot(0) -- Should be 4294967295
print("1. bnot(0) == 4294967295: " .. tostring(bnot_zero))
print("2. band(0xFF, bnot(0)) [Expected 255]: " .. tostring(bit32.band(0xFF, bnot_zero)))
print("3. band(0xFF, 0x7FFFFFFF) [Expected 255]: " .. tostring(bit32.band(0xFF, 0x7FFFFFFF)))
print("4. band(0xFF, 0x80000000) [Expected 255]: " .. tostring(bit32.band(0xFF, 0x80000000)))
print("5. band(0xFF, 0xFFFFFFFF) [Expected 255]: " .. tostring(bit32.band(0xFF, 0xFFFFFFFF)))
print("6. band(0xFFFFFFFF, 0xFF) [Expected 255]: " .. tostring(bit32.band(0xFFFFFFFF, 0xFF)))
print("7. bxor(0, 0xFFFFFFFF) [Expected 4294967295]: " .. tostring(bit32.bxor(0, 0xFFFFFFFF)))
print("8. bxor(0xFFFFFFFF, 0xFFFFFFFF) [Expected 0]: " .. tostring(bit32.bxor(0xFFFFFFFF, 0xFFFFFFFF)))
print("9. rshift(0xFFFFFFFF, 1) [Expected 2147483647]: " .. tostring(bit32.rshift(0xFFFFFFFF, 1)))
print("10. band(0xFFFFFFFF, -1) [Expected 4294967295]: " .. tostring(bit32.band(0xFFFFFFFF, -1)))Observed Results (Log Output):
1. bnot(0) == 4294967295: 4294967295
2. band(0xFF, bnot(0)) [Expected 255]: 0
3. band(0xFF, 0x7FFFFFFF) [Expected 255]: 255
4. band(0xFF, 0x80000000) [Expected 255]: 0
5. band(0xFF, 0xFFFFFFFF) [Expected 255]: 0
6. band(0xFFFFFFFF, 0xFF) [Expected 255]: 0
7. bxor(0, 0xFFFFFFFF) [Expected 4294967295]: 0
8. bxor(0xFFFFFFFF, 0xFFFFFFFF) [Expected 0]: 0
9. rshift(0xFFFFFFFF, 1) [Expected 2147483647]: 0
10. band(0xFFFFFFFF, -1) [Expected 4294967295]: 0
Conclusion:
This is a regression, as these operations previously functioned correctly. This bug prevents the use of essential algorithms, including PRNGs (like Mersenne Twister), hashing routines, and bit-packing logic, which are critical for advanced scripting.