Summary
src/Data/Int.lua declares the loop variable n in toStringAs without local, so it leaks into the global environment. luacheck --std min src/ flags it as setting non-standard global variable n, and because the rest of the function reads that name, the single missing local cascades into eight separate warnings.
Offending code
toStringAs = (function(radix)
return function(i)
local floor, insert = math.floor, table.insert
n = floor(i) -- <-- no `local`: global leak
if radix == 10 then return tostring(n) end
...
if n < 0 then
sign = "-"
n = -n
end
repeat
local d = (n % radix) + 1
n = floor(n / radix)
insert(t, 1, digits:sub(d, d))
until n == 0
...
floor and insert on the preceding line are correctly local; only n was missed.
Root cause
A plain assignment n = floor(i) instead of local n = floor(i). In Lua an unqualified assignment to an undeclared name writes to the global table _G. Every later use of n in the function then resolves to that global rather than a local.
Impact
- Functional: each call to
Data.Int.toStringAs mutates the shared global n. In a single-threaded Lua program this is usually benign, but it is an unintended global write that can collide with any other code (the FFI runtime, user code, another module) that happens to use a global named n, producing hard-to-trace cross-module interference. It is the kind of latent footgun that only manifests under specific call interleavings.
- Hygiene/tooling:
luacheck --quiet --std min src/ exits non-zero on this file. The one missing local produces these warnings:
src/Data/Int.lua:25:7: setting non-standard global variable n
src/Data/Int.lua:26:43: accessing undefined variable n
src/Data/Int.lua:30:10: accessing undefined variable n
src/Data/Int.lua:32:9: setting non-standard global variable n
src/Data/Int.lua:32:14: accessing undefined variable n
src/Data/Int.lua:35:20: accessing undefined variable n
src/Data/Int.lua:36:9: setting non-standard global variable n
src/Data/Int.lua:36:19: accessing undefined variable n
All eight collapse once n is declared local.
How it was found
Linting the FFI sources of the Lua-fork package with luacheck --quiet --std min src/ while auditing the purescript-lua package ecosystem for Lua-5.1/global-hygiene issues.
Fix
Add local to the declaration of n:
Minimal, single-line, src-only change. No behaviour change for any well-formed program; it merely confines n to the function scope where it belongs.
Note on out-of-scope warnings
The same file also reports accessing undefined field pow of global math (math.pow, removed in Lua 5.2+) and an unused argument nothing. Those are distinct pre-existing issues and are intentionally left out of this fix to keep the change minimal and focused on the global leak.
Cross-reference
Tracked upstream by pslua issue purescript-lua/purescript-lua#51; this is the detailed package-level report it points to.
Summary
src/Data/Int.luadeclares the loop variablenintoStringAswithoutlocal, so it leaks into the global environment.luacheck --std min src/flags it assetting non-standard global variable n, and because the rest of the function reads that name, the single missinglocalcascades into eight separate warnings.Offending code
floorandinserton the preceding line are correctlylocal; onlynwas missed.Root cause
A plain assignment
n = floor(i)instead oflocal n = floor(i). In Lua an unqualified assignment to an undeclared name writes to the global table_G. Every later use ofnin the function then resolves to that global rather than a local.Impact
Data.Int.toStringAsmutates the shared globaln. In a single-threaded Lua program this is usually benign, but it is an unintended global write that can collide with any other code (the FFI runtime, user code, another module) that happens to use a global namedn, producing hard-to-trace cross-module interference. It is the kind of latent footgun that only manifests under specific call interleavings.luacheck --quiet --std min src/exits non-zero on this file. The one missinglocalproduces these warnings:All eight collapse once
nis declaredlocal.How it was found
Linting the FFI sources of the Lua-fork package with
luacheck --quiet --std min src/while auditing thepurescript-luapackage ecosystem for Lua-5.1/global-hygiene issues.Fix
Add
localto the declaration ofn:Minimal, single-line,
src-only change. No behaviour change for any well-formed program; it merely confinesnto the function scope where it belongs.Note on out-of-scope warnings
The same file also reports
accessing undefined field pow of global math(math.pow, removed in Lua 5.2+) and anunused argument nothing. Those are distinct pre-existing issues and are intentionally left out of this fix to keep the change minimal and focused on the global leak.Cross-reference
Tracked upstream by pslua issue purescript-lua/purescript-lua#51; this is the detailed package-level report it points to.