On Sun, 8 Mar 2026 at 20:30, Clemens Lode <[email protected]>
wrote:
> 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
>
hm
we have now LUATEXCOREVERSION = 1.180
I understand the issue, but you should rephrase it
on the latest version of luatex-core.lua.
--
luigi
_______________________________________________
dev-luatex mailing list -- [email protected]
To unsubscribe send an email to [email protected]