From 8a42066ec571b46891ca5165840779a3b7345c96 Mon Sep 17 00:00:00 2001 From: WyattAu Date: Mon, 31 Aug 2026 19:46:31 +0100 Subject: [PATCH] Add nil guards for kpse.find_file in unicode data loading io.open(kpse.find_file"...") crashes with a cryptic error when kpse.find_file returns nil (e.g. when the unicode-data package is not installed, or when the font cache is empty/corrupted). Add nil guards with a clear error message directing users to install the 'unicode-data' TeX package. Fixes #264 Closes #335 --- src/luaotfload-multiscript.lua | 14 ++++++++++++-- src/luaotfload-notdef.lua | 14 ++++++++++++-- src/luaotfload-unicode.lua | 35 +++++++++++++++++++++++++++++----- 3 files changed, 54 insertions(+), 9 deletions(-) diff --git a/src/luaotfload-multiscript.lua b/src/luaotfload-multiscript.lua index bcf9edde..cc24873f 100644 --- a/src/luaotfload-multiscript.lua +++ b/src/luaotfload-multiscript.lua @@ -66,7 +66,12 @@ local script_extensions do * entry^0 , multirawset) - local f = io.open(kpse.find_file"ScriptExtensions.txt") + local script_extensions_file = kpse.find_file"ScriptExtensions.txt" + if not script_extensions_file then + error("luaotfload: Cannot find ScriptExtensions.txt. " + .. "Install the 'unicode-data' TeX package (tlmgr install unicode-data).") + end + local f = io.open(script_extensions_file) script_extensions = file:match(f:read'*a') f:close() for cp,t in next, script_extensions do @@ -131,7 +136,12 @@ local script_mapping do * entry^0 , multirawset) - local f = io.open(kpse.find_file"Scripts.txt") + local scripts_file = kpse.find_file"Scripts.txt" + if not scripts_file then + error("luaotfload: Cannot find Scripts.txt. " + .. "Install the 'unicode-data' TeX package (tlmgr install unicode-data).") + end + local f = io.open(scripts_file) script_mapping = file:match(f:read'*a') f:close() diff --git a/src/luaotfload-notdef.lua b/src/luaotfload-notdef.lua index 13b5d51a..765cdc35 100644 --- a/src/luaotfload-notdef.lua +++ b/src/luaotfload-notdef.lua @@ -65,7 +65,12 @@ local ignorable_codepoints do lpeg.Ct'' * entry^0 , rawset) - local f = io.open(kpse.find_file"UnicodeData.txt") + local unicode_data_file = kpse.find_file"UnicodeData.txt" + if not unicode_data_file then + error("luaotfload: Cannot find UnicodeData.txt. " + .. "Install the 'unicode-data' TeX package (tlmgr install unicode-data).") + end + local f = io.open(unicode_data_file) ignorable_codepoints = file:match(f:read'*a') f:close() entry = lpeg.Cg(codepoint_range * sep * ('Other_Default_Ignorable_Code_Point' * lpeg.Cc(true) @@ -77,7 +82,12 @@ local ignorable_codepoints do lpeg.Carg(1) * entry^0 , multirawset) - f = io.open(kpse.find_file"PropList.txt") + local proplist_file = kpse.find_file"PropList.txt" + if not proplist_file then + error("luaotfload: Cannot find PropList.txt. " + .. "Install the 'unicode-data' TeX package (tlmgr install unicode-data).") + end + f = io.open(proplist_file) ignorable_codepoints = file:match(f:read'*a', 1, ignorable_codepoints) f:close() for i = 0xFFF9,0xFFFB do diff --git a/src/luaotfload-unicode.lua b/src/luaotfload-unicode.lua index 715d4d98..078292ea 100644 --- a/src/luaotfload-unicode.lua +++ b/src/luaotfload-unicode.lua @@ -31,7 +31,12 @@ local alphnum_only do * entry^0 , rawset) - local f = io.open(kpse.find_file"UnicodeData.txt") + local unicode_data_file = kpse.find_file"UnicodeData.txt" + if not unicode_data_file then + error("luaotfload: Cannot find UnicodeData.txt. " + .. "Install the 'unicode-data' TeX package (tlmgr install unicode-data).") + end + local f = io.open(unicode_data_file) local data = file:match(f:read'*a') f:close() function alphnum_only(s) @@ -104,7 +109,12 @@ local uppercase, lowercase, ccc, cased, case_ignorable, titlecase = {}, {}, {}, end local file = entry^0 * -1 - local f = io.open(kpse.find_file"UnicodeData.txt") + local unicode_data_file2 = kpse.find_file"UnicodeData.txt" + if not unicode_data_file2 then + error("luaotfload: Cannot find UnicodeData.txt. " + .. "Install the 'unicode-data' TeX package (tlmgr install unicode-data).") + end + local f = io.open(unicode_data_file2) assert(file:match(f:read'*a')) f:close() end @@ -129,7 +139,12 @@ local props do return t end) * -1 - local f = io.open(kpse.find_file"PropList.txt") + local proplist_file = kpse.find_file"PropList.txt" + if not proplist_file then + error("luaotfload: Cannot find PropList.txt. " + .. "Install the 'unicode-data' TeX package (tlmgr install unicode-data).") + end + local f = io.open(proplist_file) props = file:match(f:read'*a') f:close() end @@ -143,7 +158,12 @@ do end end + (1-lpeg.P'\n')^0 * '\n')^0 * -1 - local f = io.open(kpse.find_file"WordBreakProperty.txt") + local wbp_file = kpse.find_file"WordBreakProperty.txt" + if not wbp_file then + error("luaotfload: Cannot find WordBreakProperty.txt. " + .. "Install the 'unicode-data' TeX package (tlmgr install unicode-data).") + end + local f = io.open(wbp_file) assert(file:match(f:read'*a')) f:close() end @@ -187,7 +207,12 @@ do end local file = (entry + nl)^0 * -1 - local f = io.open(kpse.find_file"SpecialCasing.txt") + local special_casing_file = kpse.find_file"SpecialCasing.txt" + if not special_casing_file then + error("luaotfload: Cannot find SpecialCasing.txt. " + .. "Install the 'unicode-data' TeX package (tlmgr install unicode-data).") + end + local f = io.open(special_casing_file) assert(file:match(f:read'*a')) f:close() end