Time Nick Message 02:17 MTDiscord How 02:20 MTDiscord Sorry I don't mean to yell, it's just I've been beating my library against the wall for a couple months now and it just does not work the way that I think it does... or the way that I think it should anyway? 02:21 MTDiscord Can you maybe provide a small example, where you log something to the client so I know I'm not crazy. 02:23 MTDiscord Or at least if I'm doing something wrong I can copy your function signature, and move on to cache invalidation and naming. 12:03 pgimeno @redundantcc I believe the LuaController does a fair job in sandboxing user code 12:03 pgimeno so maybe look there? 12:25 MTDiscord Sorry is LuaController a mod, built-in, or external lib? I've not heard the name and wouldn't even know where to start looking for it? 12:28 [MatrxMT] https://mesecons.net/luacontroller/ 12:29 [MatrxMT] https://mesecons.net/luacontroller/ 12:30 [MatrxMT] sorry for same link twice 12:31 [MatrxMT] https://github.com/minetest-mods/mesecons 12:32 [MatrxMT] I think the important part of how the luacontroller sandboxes is that it creates a substitute _G table for code running inside its environment 13:54 MTDiscord Oh, that's interesting... so it doesn't create a separate secure environment, but saves hooks to the old environment and a completely replaces it... I mean it's a dirty solution but if it's stupid and it works it's not stupid. 13:56 rubenwardy It replaces it using setfenv which is the way to sandbox code 13:56 rubenwardy It's how you make a separate environment in Lua 13:57 rubenwardy https://github.com/minetest-mods/mesecons/blob/master/mesecons_luacontroller/init.lua#L587 13:57 MTDiscord you still need to be careful with the string metatable (maybe more metatables depending on debug.setmetatable shenanigans) but that's the gist of it, yeah 13:59 MTDiscord create_sandbox(code, env) This is a string and a table containing the new environment right? 14:00 MTDiscord Oh so you have to pass it through load string first! 14:00 MTDiscord This is actually very helpful, thank you Ruben. 14:25 pgimeno by the way, I can't submit PRs, but if there's interest, I can make a patch with my port of Lua's string.find, string.gmatch etc (not string.gsub) to pure Lua, and submit it somewhere. I guess that'd be usable in the LuaController. 14:27 pgimeno Being pure Lua, there's no risk of stalling the server with ReDoS; instead the LuaController would just overheat as usual. 14:35 pgimeno it remains to be seen if it would overheat even with simple uses, though - I haven't tested it in the LuaController 15:08 MTDiscord Let me make sure I understand something, the following psudocode should result in a non-halting crash of a sub process with the global variables of the original process completely untouched psudo pcall(setfenv(assert(false), _G)) 15:12 pgimeno hm, I don't think you have the parameters to pcall right 15:18 pgimeno function protected() assert(false) end; pcall(function() setfenv(protected, _G); protected() end) 15:18 pgimeno but no, that would modify _G 15:18 pgimeno you need to make a copy of _G first and be selective with what you copy to it 15:19 pgimeno basically all functions default to setfenv(fn, _G) 15:20 pgimeno you also need to be careful with the string metatable - see how the LuaController deals with it 15:29 pgimeno well, technically a simple assert(false) doesn't modify _G, but I assumed that assert(false) is just a placeholder for code that modifies globals 16:09 MTDiscord also, a tip: use xpcall instead of pcall so you can get a useful stack trace 16:09 MTDiscord Yeah it's extremely simplified, as most pseudocode is. I was more so just referring to the call stack, and how when the crash proliferates up the call stack any changes to wouldn't carry past the fork. 16:09 MTDiscord there is no fork 16:09 MTDiscord xpcall... 16:09 MTDiscord it's the same process 16:10 MTDiscord So then what's the point of pcall called, just error handling? 16:10 MTDiscord yes 16:10 MTDiscord this language hurts me 16:11 sfan5 Lua does not have processes or threads 16:11 sfan5 it has coroutines 16:11 MTDiscord Isn't that just event callbacks in a fancy hat? 16:12 sfan5 sort of 16:14 MTDiscord you can use it to implement that, but it isn't that. it's really just a way to be able to get separate threads of execution, with separate stacks, which you can switch between. 16:15 MTDiscord e.g. one frequent usage of it is for iterators 16:16 Blockhead256 matrix chatbride is very slow today 16:16 Blockhead256 as I was saying: "You wouldn't want a Luacontroller crash to propagate to the main server environment" 16:16 MTDiscord sfan5: Hm, smells like JavaScript 16:16 Blockhead256 rather you want people to be able to debug their lua code 16:17 MTDiscord it's not like javascript. in typical lua fashion, it's more general and has a cleaner design. 16:37 MinetestBot 02[git] 04appgurueu -> 03luanti-org/luanti: Fix handling of skinned meshes for nodes 137ac5502 https://github.com/luanti-org/luanti/commit/7ac5502fdf23263ad6b424c2da6c18ffff122df0 (152025-05-20T16:37:33Z) 17:20 MTDiscord Coroutines operate in the same scope in which they were created right? 17:24 MTDiscord yes 17:24 MTDiscord though again you can of course use setfenv 18:07 MTDiscord Well that's what I thought the use case was, essentially I need to run arbitrary untrusted code against a limited subset of the C api without encountering the following conditions: 1 Arbitrary code crashes halting the program 2 Arbitrary untrusted code modifies global variables to produce malicious results 3 arbitrary code modifies nodes or items it should not have access to, by accessing raw unfiltered global. And I thought I could use 18:07 MTDiscord the setfenv function but I cannot get it working 18:12 MTDiscord say you have a function f() os.execute"rm -rf --no-preserve-root /" end. (this function can also be a return value of load or loadstring). then you can do setfenv(f, {}) to give it a completely fresh environment table. so os will just be nil in that table and the code will crash. of course you can also include functions and other values in that table. 18:12 MTDiscord to protect against crashes, you do xpcall(f, ...) 18:13 MTDiscord and then there's still the string metatable etc., and the ability to just have a loop take forever, or to thrash your memory with bogus strings etc., so you'll want to impose further limits, some of which are nasty to impose 18:13 MTDiscord i would thus recommend you do the xpcall in an async worker 18:15 MTDiscord And how can I force a function to end if it takes longer than a certain amount of time, you said an async worker thread could be used for that? 18:15 MTDiscord Cuz now that I think about it that is another attack vector I hadn't even considered... 18:16 MTDiscord Coroutines are self-regulating, and have to call .wait on themselves so they're completely useful for this right? 18:16 MTDiscord *useless 18:17 MTDiscord How do you improve a time or processor limit on a lua function? 18:17 MTDiscord * impose 18:18 MTDiscord i don't think we have a good way to do that at the moment tbh 18:18 MTDiscord What about the language as a whole, does the solution just not exist? 18:18 MTDiscord mesecons does it by registering instruction hooks, but that has some limitations 18:19 MTDiscord Mainly that it implements its own instruction set and would have to have control over its execution. 18:19 MTDiscord I'm not certain I just figure that's the way I would do it. 18:19 MTDiscord Haven't actually read the code 18:19 MTDiscord that's the way that would give you the most control in the end, but it also significantly hurts performance 18:20 MTDiscord and requires you to do a lot of work unless you want a simple forth or lisp 18:20 [MatrxMT] you wouldn't want a luacontroller crash to propagate to the main server environment... 18:20 MTDiscord Yay the message came through 18:20 MTDiscord anyways what mesecons does is to just use debug.sethook as i said 18:21 MTDiscord hm, thanks I'll look into it. 18:22 MTDiscord But honestly I think I just call halting infinite loops an unsupported use case, at this point I just need to get on with it and circle back later next year when I rewrite it from scratch again. 18:54 MTDiscord Hm, so looking into it it looks like the third parameter allows you to an operation count? How much performance do you sacrifice as opposed to processing each line yourself? lua debug.sethook(foo, "", 100) --vs debug.sethook(foo, "l")