2

So I've become annoyed at the global by default style in Lua. I'm trying to write a program which will make all programs that run after it incapable of creating global variables. When they try to, that variable will be set to the function environment of that program. I've come up with this, and it seems to work, but for some reason is throwing an error in [edit: 9] in the ComputerCraft rom/programs/edit. When I run a test program,

a = 1
print(a)

it works fine and prevents the global variable from being created while still allowing it to be accessed by that program, but it doesn't work for other programs. I've tried doing _G.a, local a, and other things, but all of them work. Does anyone have any ideas why it might not work on other programs?

local oldload = loadfile
function _G.loadfile(str)
  local func = oldload(str)
  local env = {}
  env._G = env
  setmetatable(env, {__index = _G, __newindex = 
    function(table, var, val)
      rawset(env, var, val)
    end})
  setfenv(func, env)
  return func
end
ViperLordX
  • 125
  • 1
  • 10

2 Answers2

1

Lua is designed to be an embedded language. This means that the ultimate arbiter is the host language, C.

One Lua script can achieve dominance over another via sandboxing techniques. You didn't fully sandbox your scripts. You changed loadfile, but you didn't change load or dofile.

But that doesn't matter. Why? Because in terms of dominance, C always wins. See, C doesn't call the Lua loadfile function. Well, it can obviously, but it usually doesn't. Instead it calls the Lua API luaL_loadfile.

Lua code can establish a sandbox for other Lua code that it directly loads. But a Lua-based sandbox has no effect on C code, unless that code is deliberately designed to live in a Lua sandbox. And most C libraries aren't.

What this means is that, once you decide to run in a C execution environment that you can't control, your Lua sandbox means nothing. The C code can, and in many cases will, load scripts outside of your control and give them whatever environments that it wants.

And there's nothing you can do about it from Lua. The only way to resolve this is to modify the Lua .dll itself to establish your sandbox.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Thank you for your answer, but I just now found and resolved the problem. Since this was designed for ComputerCraft and things are called using Lua methods, it works fine. – ViperLordX Feb 10 '16 at 00:04
0

I found out the solution. It turns out that the shell API, an API used in many ComputerCraft programs, was not in _G, thus was not accessible when I applied the sandbox. Here's my new, functional code:

local oldload = load
function _G.load(str, arg1, arg2, arg3)
  local func = oldload(str, arg1, arg2, arg3)
  local env = getfenv(func)
  if (env == _G) then
    env = {}
    env._G = env
  end
  setmetatable(env, {__index = _G, __newindex = function(table, var, val) rawset(env, var, val) end})
  setfenv(func, env)
  return func
end
ViperLordX
  • 125
  • 1
  • 10