Skip to content

Commit b99c5da

Browse files
committed
-
1 parent c1b8918 commit b99c5da

1 file changed

Lines changed: 118 additions & 20 deletions

File tree

plugins/LuaScripting/src/modules/Module.cpp

Lines changed: 118 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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

598604
const 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

Comments
 (0)