@@ -167,18 +167,26 @@ bool Module::load(Ltg::IDatasModelWeak vDatasModel) {
167167 return sol::stack::push (L, errorMessage);
168168 });
169169
170- m_luaPtr->open_libraries (sol::lib::base);
171- m_luaPtr->open_libraries (sol::lib::package);
172- m_luaPtr->open_libraries (sol::lib::coroutine);
173- m_luaPtr->open_libraries (sol::lib::string);
174- m_luaPtr->open_libraries (sol::lib::os);
175- m_luaPtr->open_libraries (sol::lib::math);
176- m_luaPtr->open_libraries (sol::lib::table);
177- m_luaPtr->open_libraries (sol::lib::debug);
178- m_luaPtr->open_libraries (sol::lib::bit32);
179- m_luaPtr->open_libraries (sol::lib::io);
180- m_luaPtr->open_libraries (sol::lib::ffi);
181- m_luaPtr->open_libraries (sol::lib::jit);
170+ // Curated Lua stdlib for a log-parsing context. The set below covers everything a parsing
171+ // script realistically needs while closing off escape routes that don't belong in the
172+ // sandbox:
173+ // - `io` / `ffi` removed: file I/O and raw C call-out are full sandbox escapes — a
174+ // malicious or buggy script could trash arbitrary files (io) or corrupt memory (ffi).
175+ // The canonical signal sink is `ltg:addSignal*`, not file write.
176+ // - `debug` removed: a user `debug.sethook(...)` would silently override our line hook
177+ // and break the debugger. We use lua_sethook from C directly, no need to expose it.
178+ // - `package` removed: not needed for self-contained parsing scripts; will come back
179+ // when multi-script support + a local-lib folder next to the binary lands (the user
180+ // explicitly flagged this in advance, do not remove this comment when re-adding it).
181+ // - `bit32` removed: Lua 5.2 backport; LuaJIT ships `bit` natively (auto-loaded via
182+ // `jit`), so bit32 is redundant.
183+ // - `coroutine` removed: exotic in a parsing loop, never seen in practice on logs.
184+ m_luaPtr->open_libraries (sol::lib::base); // globals: tostring/tonumber/pairs/pcall/setmetatable/...
185+ m_luaPtr->open_libraries (sol::lib::string); // pattern matching, format — core for parsing
186+ m_luaPtr->open_libraries (sol::lib::math); // numeric ops
187+ m_luaPtr->open_libraries (sol::lib::table); // insert/concat/sort/remove
188+ m_luaPtr->open_libraries (sol::lib::os); // date/time/clock — log timestamps
189+ m_luaPtr->open_libraries (sol::lib::jit); // we drive jit.off/on around debug sessions
182190
183191 m_luaPtr->set_function (" print" , [](sol::variadic_args args) {
184192 std::string res;
@@ -327,17 +335,15 @@ void Module::m_ensureCompletionState() {
327335 // when no IDatasModel is bound) because we only need the usertype methods to be REGISTERED in the
328336 // metatable for introspection — none of them is ever actually called from the completion state.
329337 m_completionLuaPtr = std::unique_ptr<sol::state>(new sol::state ());
338+ // mirror the main VM's stdlib set so completion shows the same `math.*` / `string.*` / `table.*`
339+ // / `os.*` keys the user can actually call at runtime. The sandbox exec for setProjectScriptCode
340+ // has its own narrower allowlist (kSafeStdlib) — that's a separate concern, the completion
341+ // state itself doesn't run user code.
330342 m_completionLuaPtr->open_libraries (sol::lib::base);
331- m_completionLuaPtr->open_libraries (sol::lib::package);
332- m_completionLuaPtr->open_libraries (sol::lib::coroutine);
333343 m_completionLuaPtr->open_libraries (sol::lib::string);
334- m_completionLuaPtr->open_libraries (sol::lib::os);
335344 m_completionLuaPtr->open_libraries (sol::lib::math);
336345 m_completionLuaPtr->open_libraries (sol::lib::table);
337- m_completionLuaPtr->open_libraries (sol::lib::debug);
338- m_completionLuaPtr->open_libraries (sol::lib::bit32);
339- m_completionLuaPtr->open_libraries (sol::lib::io);
340- m_completionLuaPtr->open_libraries (sol::lib::ffi);
346+ m_completionLuaPtr->open_libraries (sol::lib::os);
341347 m_completionLuaPtr->open_libraries (sol::lib::jit);
342348
343349 // clang-format off
@@ -596,8 +602,9 @@ struct SignatureEntry {
596602};
597603
598604const std::vector<SignatureEntry>& s_signatureCatalog () {
605+ // clang-format off
599606 static const std::vector<SignatureEntry> catalog = {
600- // ltg: usertype methods (cf. new_usertype<LuaDatasModel> in Module::load)
607+ // -------- ltg: usertype methods (cf. new_usertype<LuaDatasModel> in Module::load) --------
601608 {" ltg" , " stringToEpoch" , {{" dateTime" ," string" }, {" hourOffset" ," number" }}},
602609 {" ltg" , " epochToString" , {{" epochTime" ," number" }, {" hourOffset" ," number" }}},
603610 {" ltg" , " addSignalTag" , {{" epoch" ," number" }, {" r" ," number" }, {" g" ," number" }, {" b" ," number" }, {" a" ," number" }, {" name" ," string" }, {" help" ," string" }}},
@@ -611,7 +618,98 @@ const std::vector<SignatureEntry>& s_signatureCatalog() {
611618 {" ltg" , " logDebug" , {{" message" ," string" }}},
612619 {" ltg" , " getRowIndex" , {}},
613620 {" ltg" , " getRowCount" , {}},
621+
622+ // -------- math.* (LuaJIT 5.1 stdlib) --------
623+ // Overloaded variants (max/min/random with varying arity) are listed with their canonical
624+ // form; the host shows one signature line, no overload picker yet.
625+ {" math" , " abs" , {{" x" ," number" }}},
626+ {" math" , " ceil" , {{" x" ," number" }}},
627+ {" math" , " floor" , {{" x" ," number" }}},
628+ {" math" , " fmod" , {{" x" ," number" }, {" y" ," number" }}},
629+ {" math" , " modf" , {{" x" ," number" }}},
630+ {" math" , " max" , {{" x" ," number" }, {" ..." ," number" }}},
631+ {" math" , " min" , {{" x" ," number" }, {" ..." ," number" }}},
632+ {" math" , " exp" , {{" x" ," number" }}},
633+ {" math" , " log" , {{" x" ," number" }}},
634+ {" math" , " log10" , {{" x" ," number" }}},
635+ {" math" , " pow" , {{" x" ," number" }, {" y" ," number" }}},
636+ {" math" , " sqrt" , {{" x" ," number" }}},
637+ {" math" , " sin" , {{" x" ," number" }}},
638+ {" math" , " cos" , {{" x" ," number" }}},
639+ {" math" , " tan" , {{" x" ," number" }}},
640+ {" math" , " asin" , {{" x" ," number" }}},
641+ {" math" , " acos" , {{" x" ," number" }}},
642+ {" math" , " atan" , {{" x" ," number" }}},
643+ {" math" , " atan2" , {{" y" ," number" }, {" x" ," number" }}},
644+ {" math" , " sinh" , {{" x" ," number" }}},
645+ {" math" , " cosh" , {{" x" ," number" }}},
646+ {" math" , " tanh" , {{" x" ," number" }}},
647+ {" math" , " deg" , {{" x" ," number" }}},
648+ {" math" , " rad" , {{" x" ," number" }}},
649+ {" math" , " frexp" , {{" x" ," number" }}},
650+ {" math" , " ldexp" , {{" x" ," number" }, {" e" ," number" }}},
651+ {" math" , " random" , {{" m" ," number?" }, {" n" ," number?" }}},
652+ {" math" , " randomseed" , {{" seed" ," number" }}},
653+
654+ // -------- string.* (LuaJIT 5.1 stdlib) --------
655+ // All also callable as method on a string via metatable (`s:match(...)`); the signature
656+ // catalog matches the `string.fn(s, ...)` namespace form — the trigger doesn't try to
657+ // resolve `s:match(...)` to the string lib (would need type inference).
658+ {" string" , " byte" , {{" s" ," string" }, {" i" ," number?" }, {" j" ," number?" }}},
659+ {" string" , " char" , {{" ..." ," number" }}},
660+ {" string" , " find" , {{" s" ," string" }, {" pattern" ," string" }, {" init" ," number?" }, {" plain" ," boolean?" }}},
661+ {" string" , " format" , {{" fmt" ," string" }, {" ..." ," any" }}},
662+ {" string" , " gmatch" , {{" s" ," string" }, {" pattern" ," string" }}},
663+ {" string" , " gsub" , {{" s" ," string" }, {" pattern" ," string" }, {" repl" ," string|table|function" }, {" max" ," number?" }}},
664+ {" string" , " len" , {{" s" ," string" }}},
665+ {" string" , " lower" , {{" s" ," string" }}},
666+ {" string" , " match" , {{" s" ," string" }, {" pattern" ," string" }, {" init" ," number?" }}},
667+ {" string" , " rep" , {{" s" ," string" }, {" n" ," number" }, {" sep" ," string?" }}},
668+ {" string" , " reverse" , {{" s" ," string" }}},
669+ {" string" , " sub" , {{" s" ," string" }, {" i" ," number" }, {" j" ," number?" }}},
670+ {" string" , " upper" , {{" s" ," string" }}},
671+ {" string" , " dump" , {{" f" ," function" }}},
672+
673+ // -------- table.* (LuaJIT 5.1 stdlib) --------
674+ // insert is overloaded (insert(t, v) or insert(t, pos, v)); listed with the widest form.
675+ {" table" , " concat" , {{" t" ," table" }, {" sep" ," string?" }, {" i" ," number?" }, {" j" ," number?" }}},
676+ {" table" , " insert" , {{" t" ," table" }, {" pos" ," number?" }, {" value" ," any" }}},
677+ {" table" , " remove" , {{" t" ," table" }, {" pos" ," number?" }}},
678+ {" table" , " sort" , {{" t" ," table" }, {" comp" ," function?" }}},
679+ {" table" , " maxn" , {{" t" ," table" }}},
680+
681+ // -------- os.* (subset useful for log parsing) --------
682+ // io.* deliberately omitted — file I/O from a parsing script is a smell; ltg:* is the
683+ // canonical sink for signals/tags/values.
684+ {" os" , " date" , {{" format" ," string?" }, {" time" ," number?" }}},
685+ {" os" , " time" , {{" table" ," table?" }}},
686+ {" os" , " difftime" , {{" t2" ," number" }, {" t1" ," number" }}},
687+ {" os" , " clock" , {}},
688+ {" os" , " getenv" , {{" name" ," string" }}},
689+
690+ // -------- base lib (globals — target left empty) --------
691+ // The trigger fires on `funcName(` at top level (no dot/colon prefix). Common scaffolding
692+ // for parsing scripts: tostring/tonumber/pairs/ipairs/type/pcall/setmetatable.
693+ {" " , " tostring" , {{" v" ," any" }}},
694+ {" " , " tonumber" , {{" v" ," any" }, {" base" ," number?" }}},
695+ {" " , " type" , {{" v" ," any" }}},
696+ {" " , " select" , {{" n" ," number|string" }, {" ..." ," any" }}},
697+ {" " , " pairs" , {{" t" ," table" }}},
698+ {" " , " ipairs" , {{" t" ," table" }}},
699+ {" " , " next" , {{" t" ," table" }, {" key" ," any?" }}},
700+ {" " , " unpack" , {{" list" ," table" }, {" i" ," number?" }, {" j" ," number?" }}},
701+ {" " , " assert" , {{" v" ," any" }, {" msg" ," string?" }}},
702+ {" " , " error" , {{" msg" ," any" }, {" level" ," number?" }}},
703+ {" " , " pcall" , {{" f" ," function" }, {" ..." ," any" }}},
704+ {" " , " xpcall" , {{" f" ," function" }, {" handler" ," function" }, {" ..." ," any" }}},
705+ {" " , " setmetatable" , {{" t" ," table" }, {" mt" ," table|nil" }}},
706+ {" " , " getmetatable" , {{" t" ," table" }}},
707+ {" " , " rawget" , {{" t" ," table" }, {" k" ," any" }}},
708+ {" " , " rawset" , {{" t" ," table" }, {" k" ," any" }, {" v" ," any" }}},
709+ {" " , " rawequal" , {{" a" ," any" }, {" b" ," any" }}},
710+ {" " , " print" , {{" ..." ," any" }}},
614711 };
712+ // clang-format on
615713 return catalog;
616714}
617715
0 commit comments