Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using _ENV to overwrite a scope #275

Open
bczsalba opened this issue Dec 25, 2024 · 6 comments
Open

Using _ENV to overwrite a scope #275

bczsalba opened this issue Dec 25, 2024 · 6 comments

Comments

@bczsalba
Copy link

Is there any way to use _ENV with Lupa? From my testing I've gathered that each call to either .execute or .eval resets/uses its own _ENV, so if you set it in one call it resets by the next.

Reproduction

from lupa import LuaRuntime

lua = LuaRuntime()

code = """
    hidden = 1
    print(hidden)
    
    _ENV = { print = print }
    
    print(hidden)
"""

for line in code.splitlines():
    lua.exec(line)

The Lua code outputs 1 then nil (like on this compiler), but using Lupa results in 1 and 1.

Context

I'm using Lupa to embed Lua into a UI library I'm making. Each widget has its own script, and their _ENV-s create a sort of cascade where each widget within a container has access to things defined above it, but not to its siblings. The end goal is something like Alpine.js.

I suspect the same cascade would be possible using functions instead of inline do ... end scopes, but that massively complicates everything.

Cheers, and enjoy the holidays!

@Kirstukas
Copy link

I ran a couple of tests on WSL, these are the results:

Lua 5.1
1
1

Lua 5.2
1
nil

Lua 5.3
1
nil

Lua 5.4
1
nil

LuaJIT 2.1
1
1

Try importing like this:

from lupa.lua54 import LuaRuntime

_ENV was added in Lua 5.2, replacing setfenv.

I would suggest looking into load(chunk, type, env), instead of modifying _ENV directly.

@bczsalba
Copy link
Author

bczsalba commented Feb 11, 2025

@Kirstukas Did you run this in Lupa or just Lua? In your output 5.1 and JIT 2.1 are incorrect in their output, the rest are correct.

load is a good suggestion, but isn't what I needed (I got around the problem by building up the snippet and then executing it all at once). Overwriting _ENV is an intentional feature, and is the most commonly recommended way to sandbox Lua past 5.2. If there is a technical reason not to support it I'm also fine with that (again, I did get around it), but it would be nice to have it documented so the next guy doesn't have to spend a day trying to understand why something works in seemingly every Lua compiler but not in Lupa :)

@Kirstukas
Copy link

I think that the issue is that you are executing it line by line. I think that execute compiles code into a function (just like load in Lua) and then runs it. Because _ENV variable is scoped locally to a function, the effect is not carried over.

Instead of:

for line in code.splitlines():
    lua.execute(line)

Try:

lua.execute(code)

@bczsalba
Copy link
Author

Yes, that's what I assumed was happening in the initial report:

From my testing I've gathered that each call to either .execute or .eval resets/uses its own _ENV, so if you set it in one call it resets by the next.

I would just like a way to either:

  • Share _ENV between calls (could be enabled by a toggle)
  • Documentation of this behaviour ("Each call to .execute and .eval create their own environments, so overwriting _ENV in one call will not affect subsequent calls")

@Kirstukas
Copy link

This is Lua behaviour, not specific to Lupa.

You can store _ENV to an external variable, and assign it when needed.

sandboxed_env = {...}

function wrapper()
    local _ENV = sandboxed_env

    -- Will use sandboxed_env
    some_callback()
end

But be carefull with load as it loads chunk into "default environment", thus escaping the sandbox.

@bczsalba
Copy link
Author

Yes, again I knew all of this before I made the issue. I laid out my request in my previous comment, but here it is again:

  • Share _ENV between calls (could be enabled by a toggle)
  • Documentation of this behaviour ("Each call to .execute and .eval create their own environments, so overwriting _ENV in one call will not affect subsequent calls")

I'll just wait for a maintainer's response now. You don't seem to be one (correct me if I'm wrong), so us going back and forth isn't doing anyone any good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants