moonsharp-devs / moonsharp

An interpreter for the Lua language, written entirely in C# for the .NET, Mono, Xamarin and Unity3D platforms, including handy remote debugger facilities.
http://www.moonsharp.org
Other
1.42k stars 214 forks source link

Loaded code does not contain a _ENV upvalue #126

Closed lightspeedlucas closed 8 years ago

lightspeedlucas commented 8 years ago

The title might be wrong (I'm very new to Lua), but I think that's the issue behind this. The code below comes from a StackOverflow answer and behaves differently in MoonSharp. The second to last print fails, meaning that debug.setupvalue could not change _ENV. In other implementations of Lua it works fine.

function print_env()
  print(_ENV)
end

function sandbox()
  print(_ENV) -- prints: "table: 0x100100610"
  -- need to keep access to a few globals:
  _ENV = { print = print, print_env = print_env, debug = debug, load = load }
  print(_ENV) -- prints: "table: 0x100105140"
  print_env() -- prints: "table: 0x100105140"
  local code1 = load('print(_ENV)')
  code1()     -- prints: "table: 0x100100610"
  debug.setupvalue(code1, 1, _ENV) -- set our modified env
  code1()     -- prints: "table: 0x100105140"
  local code2 = load('print(_ENV)', nil, nil, _ENV) -- pass 'env' arg
  code2()     -- prints: "table: 0x100105140"
end

sandbox()
xanathar commented 8 years ago

Title is right. On the outmost chunks, _ENV is a local instead of an upvalue, differently from standard Lua. It's a difference which almost never counts, except in the above code. If it isn't too hard I'll fix it before next release.

lightspeedlucas commented 8 years ago

Oh, I see. Thanks for looking into it. It seems to be very useful when sandboxing. I'd love to be able to do [Chunk's Closure].GetUpvalue(0).Assign(DynValue.NewTable(NewEnvironment)); from C#.

xanathar commented 8 years ago

Apart from the fact that this is a bug and will be fixed :grin: .. but.. have you considered the other ways of sandboxing ? (like loading into a different Script object for example, with very limited modules selection by using a CoreModules preset, etc.) ?

lightspeedlucas commented 8 years ago

Yes! I'm currently designing a Lua API for a game in Unity to customize some object behaviors. The basic idea is that the user writes a class in Lua to control the behavior of some entity and for each instance of this entity, an instance of that class is created.

Right now I'm doing unique global tables for each behavior's class, so that a class (written by Alice) cannot interfere with another (written by Bob), but instances of the same class can share stuff globally. All nicely sandboxed with CoreModules presets.

I was experimenting with the ENV technique to simplify the design so that users don't need to mess with OOP if they don't want to, I'd just create a unique environment for each instance of a behavior. I came across this little bug while testing the idea.

xanathar commented 8 years ago

Whoo very complex scenario.. let me know if you encounter any other issue.

In the meantime, fixed, committed and released.