On Windows, io.open() returns nil, nil when opening a path returned by
os.tmpname() for writing. The second return value should be an error
string per the Lua 5.3 reference manual (§6.8), but it is nil. This
appears to happen because openout_any = p (paranoid mode) blocks writes
outside the current working directory. os.tmpname() returns an absolute
path to the system temp directory, which is outside CWD. The blocking
itself is reasonable, but the missing error string makes debugging
difficult.
LuaHBTeX version: tested both 1.22.0 (TeX Live 2025, Windows), and
1.24.0 (TeX Live 2026, Windows)
MWE:
\documentclass{article}
\begin{document}
\directlua{
local t = os.tmpname()
local f, e = io.open(t, "w")
texio.write_nl("tmpname: " .. t)
texio.write_nl("file: " .. tostring(f))
texio.write_nl("error: " .. tostring(e))
local f2, e2 = io.open("test-cwd.tmp", "w")
texio.write_nl("cwd file: " .. tostring(f2))
if f2 then f2:close(); os.remove("test-cwd.tmp") end
}
\end{document}
Output:
tmpname: C:\Users\Clemens\AppData\Local\Temp\s1gyk.0
file: nil
error: nil
cwd file: file (0000000007DDFAB0)
Expected: The error line should contain a descriptive string (e.g.,
"Permission denied") rather than nil.
Root cause in luatex-core.lua (v1.161):
The luatex_io_open override (lines 65-76) delegates to validoutput:
local function validoutput(name,how)
return type(how) == "string" and find(how,"w") and
kpse_outputnameok(name) and io_open(name,how)
end
When kpse_outputnameok(name) returns false, Lua's short-circuit "and"
stops the chain and returns false -- the real io_open is never called,
so no error string is ever produced. luatex_io_open then returns this
bare falsy value with no second return value, violating the io.open
contract (nil, errmsg, errno).
The same issue exists in luatex_io_open_readonly (lines 78-84).
Suggested fix:
local function luatex_io_open(name,how)
local handle = validinput(name,how)
if handle then
kpse_recordinputfile(name,"r")
else
handle = validoutput(name,how)
if handle then
kpse_recordoutputfile(name,"w")
end
end
if not handle then
return nil, name .. ": kpse permission denied"
end
return handle
end
Best regards,
Clemens
_______________________________________________
dev-luatex mailing list -- [email protected]
To unsubscribe send an email to [email protected]