Making global environment access-only (Lua) - lua

I embedded Lua and want scripts to be able to read the global table but not automatically write to it so two scripts can write variables with the same name without overwriting eachother but still being able to add stuff to the global table. I can't really explain it better then this:
Script 1
var1 = "foo"
_G.var2 = "bar"
Script 2
print(var1) -- Prints nil
print(var2) -- Prints 'bar'
How I tried to accomplish this is by doing something like this (The 'scripts' being a function)
newScript = function(content)
Script = loadstring(content)()
env = setmetatable({},{__index = _G})
setfenv(Script,env)
return Script
end
My Lua binding is LuaJ, for the sake of giving all information here is that code too:
private LuaValue newScript(String content){
LuaTable envMt = new LuaTable();
envMt.set(INDEX, _G);
LuaTable env = new LuaTable();
env.setmetatable(envMt);
LuaClosure func = (LuaClosure) _G.get("loadstring").call(valueOf(content));
thread = new LuaThread(func,env);
thread.resume(NIL);
return thread;
}

It's not __index that you want to change, it's __newindex. In addition, you can't use __index to catch access to keys that do exist in the table. The only way to make a table read-only in all situations is to defer all reads to a proxy table and throw an error on writes.

Here's a function I use to return a read-only table:
function ro_table (t)
local t = t
if t then
return setmetatable({},
{ __index=t,
__newindex= function(_,_,_) error ("Attempt to modify read-only table") end,
})
else
return nil
end
end
So for your code, you'd have the following:
newScript = function(content)
Script = loadstring(content)()
setfenv(Script,ro_table(_G))
return Script
end
Note that this does not work recursively, so if you have any table defined as a global (or even any of the built-in functions) the contents can be changed, but the table itself cannot be replaced.

Related

How to run a string and get a table that has all the variables that the code created in lua?

So i'm making my own OS for LIKO-12 and I need to run .lk12 files but i need to have a function to run a string as code and return a table that has all of the variables that code created
Example:
function foo()
return "Hello,"
end
function bar()
return " World!"
end
hello = foo()..bar()
should return a table with 2 functions:
A function called foo that returns "Hello,"
A function called bar that returns " World!"
and a variable called hello that has "Hello, World!"
You should be able to call a function from the code using
vars["foo"]() or vars.foo()
Can anyone help me?
When you create or use a global variable it's actually stored in a table called "the environment", or _ENV (which is not global, it's a local that you get automatically)
So your code:
function foo()
return "Hello,"
end
function bar()
return " World!"
end
hello = foo()..bar()
is really doing:
function _ENV.foo()
return "Hello,"
end
function _ENV.bar()
return " World!"
end
_ENV.hello = _ENV.foo().._ENV.bar()
so if we just set _ENV to a new table, and return it, then this is exactly the table you want. You can do this with load (which is how you run strings) by passing it as the 4th argument. This function will do that:
function loadAndReturnEnv(codeString)
local env = {}
load(codeString, nil, nil, env)() -- error checking skipped for demonstration
return env
end
However, note that all the usual global stuff like string.rep, table.sort, load, print don't exist in this new _ENV. If that's what you want, that's great. But I guess you probably do want them. In that case we can use the metatable __index feature, so that if the code looks for something in its _ENV and it's not there, it looks in our (the caller's) _ENV instead.
function loadAndReturnEnvWithGlobals(codeString)
-- note: env is the environment for the code we're about to run
-- (which will be called _ENV in that code), and _ENV is the environment
-- of the loadAndReturnEnvWithGlobals function (i.e. the "real" environment)
local env = {}
setmetatable(env, {__index=_ENV})
load(codeString, nil, nil, env)() -- error checking skipped for demonstration
setmetatable(env, nil) -- set the table back to normal before we return it
return env
end
But wait... the program can now call print when you run it, but if it defines a function, that function can't call print since we deleted the link back to the real environment after the code returned. So I think the best way to fix that is to leave the environment linked, and just copy the functions etc.
function loadAndReturnEnvWithGlobals2(codeString)
local env = {}
setmetatable(env, {__index=_ENV})
load(codeString, nil, nil, env)() -- error checking skipped for demonstration
local result = {}
for k,v in pairs(env) do result[k]=v end
return result
end
although this copies the values, so if you have any functions that change the variables, you won't see the changed variables.
Which version you use is up to you. They each have pros and cons.

How to make global variables "immutable" in Lua/LuaJ?

Description
I'm doing a LuaJ program, and here's a lib script like this:
function foo()
print("foo");
end
I want the foo function can be invoked in other scripts directly (no require), but performs immutable in different scripts. ( Even a script overrides it, it performs as the original way in other scripts. )
For example, here's the script 1:
foo = function()
print("bar");
end
and here is the script 2:
foo();
What's done
I have saw these two questions. They do work but not the solution to this problem.
LuaJ How to avoid overriding existing entries in Globals table
Preventing Function Overriding in Lua Table
Making global environment access-only (Lua)
I tried loading lib every time exec a script, or set local _ENV, but because there may be further callbacks from Java to Lua, it doesn't work correctly.
I now handle it by create a Globals and load lib script every time load a script in Java like this:
public static void main(String[] args) {
loadAndCallViaDifferentEnv(libPath, script1);
loadAndCallViaDifferentEnv(libPath, script2);
}
static void loadAndCallViaDifferentEnv(String libPath, String scriptPath) {
Globals globals = JsePlatform.standardGlobals();
globals.loadfile(libPath).call();
globals.loadfile(scriptPath).call();
}
It works well, but costs much. Is there a better way?
I assume you want to protect three functions from overwriting: foo1, foo2 and print
-- define foo1 and foo2 inside protected table instead of as usual globals
local protected = {}
function protected.foo1()
print("foo1");
end
function protected.foo2()
print("foo2");
end
-- if a function to be protected already exists, remove it from globals:
protected.print = print
print = nil
-- Now set the metatable on globals
setmetatable(_G, {
__index = protected,
__newindex =
function(t, k, v)
if not protected[k] then
rawset(t, k, v)
end
end
})
Now you can invoke foo1, foo2 and print from other modules without require, but you can not overwrite them:
-- the script 1:
foo1 = function()
print("bar");
end
foo1(); -- original protected.foo1() is invoked
-- the script 2:
foo1(); -- original protected.foo1() is invoked

Intercept Global Function

Is it possible to intercept a global function call, and run another function when the global is called.
local test = global()
function test()
print("Hello World")
end
I've tried this but it doesn't seem to work.
Edit
My original question was phrased poorly I ended up coming up with this solution. The functions I'm trying to change are inside of a table so I just make a copy of the table, overwrite the function and then copy the backup table over the original to restore the function.
copy = {}
i,v = next(globaltable, nil)
while i do
copy[i] = v
i,v = next(globaltable,i)
end
function globaltable:function()
do some stuff
globaltable = copy
end
If you want to actually call test when calling global(), assign test to global:
local old_global = global
global = test
This makes global to refer to the function object of test.

Lua scripts stored in memory

I'm facing problem with lua,
Everytime I'm executing a function/command or even define a variable, everything is stored as a string in memory.
And it can be read via programs like Cheat Engine or HxD
For example
x = 'Test'
If I search for the string x = '
I will be able to extra the whole command from memory.
Same for functions
function Test()
print(1);
end
Searching Test() will allow me to obtain the whole function script.
Here's an example image
http://i40.tinypic.com/6oh281.png
as you can see in the bottom of the Memory Viewer window, theres the whole function information.
Now how could I prevent lua from creating 'extra' copies of the script in memory?
Garbagecollector does not wipe it out.
Any solution or idea to prevent this would be welcomed.
I’m not sure what you mean but try luaL_loadbuffer(L,script,strlen(script),”=noname”)for loading scripts. If you use luaL_dostring then the entire script is saved as its own name.
Note also that you can load a script once and run it multiple times, without having to load it again.
You don't need to load the Lua source of a script at all. Pre-compile the script with luac -s. Of course, the Lua bytecode and strings will still be accessible in memory and just as easily found.
Update
The output of luac is a script in binary form. Use it just like a Lua script. You can use it with loadstring, loadfile etc.
Make your test.lua:
print("testing")
Test:
luac -o test.lub -s test.lua
lua test.lua
lua test.lub
To see what you are exposing vs the Lua source:
luac -l test.lub
By default lua stores the key(x) as string, and value as object on memory, There's not much you can do with it except managing your scripts and storing values inside a block only. Still, This way can be detected by cheat-engines but it's a lot more secure than default.
safe.lua:
local protected = {}
protected.x = "Test"
safe = {}
function safe.Get(pass, val)
if pass == "0x012345" then
if not protected[val] then return nil end
return protected[val]
end
return nil
end
function safe.Set(pass, val, key)
if not pass == "0x012345" then return end
protected[val] = key
end
function safe.Remove(pass, val)
if not pass == "0x012345" then return end
if not protected[val] then return end
protected[val] = nil
end
test.lua:
safe.Set("0x012345", "b", {C = "111"})
print(safe.Get("0x012345", "b").C)
If you want to use a custom pass for each key, then use this safe.lua:
local protected = {}
safe = {}
function safe.Get(pass, val)
if protected[val] then
if not protected[val][pass] then return nil end
return protected[val][pass]
end
return nil
end
function safe.Set(pass, val, key)
protected[val] = {}
protected[val][pass] = key
end
function safe.Remove(pass, val)
if not protected[val] then return end
if not protected[val][pass] then return end
protected[val][pass] = nil
end
and test.lua:
safe.Set("tsting", "x", "keey")
print(safe.Get("tsting", "x"))
print(safe.Get("testing", "x"))

Globals are bad, does this increase performance in any way?

I'm working in LuaJIT and have all my libraries and whatnot stored inside "foo", like this:
foo = {}; -- The only global variable
foo.print = {};
foo.print.say = function(msg) print(msg) end;
foo.print.say("test")
Now I was wondering, would using metatables and keeping all libraries local help at all? Or would it not matter. What I thought of is this:
foo = {};
local libraries = {};
setmetatable(foo, {
__index = function(t, key)
return libraries[key];
end
});
-- A function to create a new library.
function foo.NewLibrary(name)
libraries[name] = {};
return libraries[name];
end;
local printLib = foo.NewLibrary("print");
printLib.say = function(msg) print(msg) end;
-- Other file:
foo.print.say("test")
I don't really have the tools to benchmark this right now, but would keeping the actual contents of the libraries in a local table increase performance at all? Even the slightest?
I hope I made mysef clear on this, basically all I want to know is: Performance-wise is the second method better?
If someone could link/give a detailed explaination on how global variables are processed in Lua which could explain this that would be great too.
don't really have the tools to benchmark this right now
Sure you do.
local start = os.clock()
for i=1,100000 do -- adjust iterations to taste
-- the thing you want to test
end
print(os.clock() - start)
With performance, you pretty much always want to benchmark.
would keeping the actual contents of the libraries in a local table increase performance at all?
Compared to the first version of the code? Theoretically no.
Your first example (stripping out the unnecessary cruft):
foo = {}
foo.print = {}
function foo.print.say(msg)
print(msg)
end
To get to your print function requires three table lookups:
index _ENV with "foo"
index foo table with "print"
index foo.print table with "say".
Your second example:
local libraries = {}
libraries.print = {}
function libraries.print.say(msg)
print(msg)
end
foo = {}
setmetatable(foo, {
__index = function(t, key)
return libraries[key];
end
});
To get to your print function now requires five table lookups along with other additional work:
index _ENV with "foo"
index foo table with "print"
Lua finds the result is nil, checks to see if foo has a metatable, finds one
index metatable with "__index"
check to see if the result is is is table or function, Lua find it's a function so it calls it with the key
index libraries with "print"
index the print table with "say"
Some of this extra work is done in the C code, so it's going to be faster than if this was all implemented in Lua, but it's definitely going to take more time.
Benchmarking using the loop I showed above, the first version is roughly twice as fast as the second in vanilla Lua. In LuaJIT, both are exactly the same speed. Obviously the difference gets optimized away at runtime in LuaJIT (which is pretty impressive). Just goes to show how important benchmarking is.
Side note: Lua allows you to supply a table for __index, which will result in a lookup equivalent to your code:
setmetatable(foo, { __index = function(t, key) return libraries[key] end } )
So you could just write:
setmetatable(foo, { __index = libraries })
This also happens to be a lot faster.
Here is how I write my modules:
-- foo.lua
local MyLib = {}
function MyLib.foo()
...
end
return MyLib
-- bar.lua
local MyLib = require("foo.lua")
MyLib.foo()
Note that the return MyLib is not in a function. require captures this return value and uses it as the library. This way, there are no globals.

Resources