15 Jan, 2012, Omega wrote in the 1st comment:
Votes: 0
Currently I have my C++ functions bound to lua; I can push data back/forth, pretty easily, but I am having a problem with one part of my code: I'll note this, I am using LUA 5.2 library.

bool LuaEngine::runLuaCommand( Creature *c, const std::string &after )
{
bool match = false;
if(!c)
return false;

try {
int top = lua_gettop(mLuaVM);
lua_getglobal(mLuaVM, "sandstorm");
lua_getfield(mLuaVM, -1, "runcommand");
if(!lua_isfunction(mLuaVM, -1))
{
lua_pop(mLuaVM,1);
Log::instance().bug(eLOGLOW, "Warning: Lua script function '%s' does not exist", "sandstorm.runcommand");
return false;
}
SandBind::push<Creature*>(mLuaVM, c);
lua_pushstring( mLuaVM, after.c_str() );

if ( lua_pcall( mLuaVM, 2, 1, 0 ) != 0 )
Log::instance().bug(eLOGLOW, "lua: function 'sandstorm.runcommand': (%s) %s", c->getName().c_str(), lua_tostring( mLuaVM, -1 ) );
if ( !lua_isboolean( mLuaVM, -1 ) )
return false;
match = lua_toboolean( mLuaVM, -1 );
lua_pop( mLuaVM, 1 );
} catch (std::exception &e) {
Log::instance().exception(eLOGLOW, e.what());
} catch (…) {
Log::instance().exception(eLOGLOW, "An unknown error has occured from within runLuaCommand!");
}

return match;
}


The problem is either lua_getfield isn't working properly anymore since the 5.2 change, or I've done something horrifically wrong.

The lua-code it is trying to call is:

function sandstorm.runcommand( c, after )
c:writeBuffer "Successful push"
return 1
end


No syntax errors or problems in the lua code are detected.

I get 'Warning: Lua script function 'runcommand' does not exist ' because it doesn't detect the function. lua_getfield should identify it within the table sandstorm.
23 Jan, 2012, David Haley wrote in the 2nd comment:
Votes: 0
Are you sure that the table has been populated at this point? If it's not a function, what is it – nil, something else? What all is in the table?

BTW your code has a memory leak; you're getting the global table but you're never popping it off the stack.
23 Jan, 2012, Omega wrote in the 3rd comment:
Votes: 0
I found/fixed the error, took some doing, but it was else-where and it wasn't dropping any errors from it (thought it should of). As for the memory leak, thanks! I didn't notice that. :) Much appreciated David!

With that said, I have it fully integrated now, and I'm quite happy!

Again, thanks for spotting the leak!
23 Jan, 2012, David Haley wrote in the 4th comment:
Votes: 0
Cool, glad that you got it worked out. :smile:

I found that dealing with that kind of thing was one of the more challenging aspects of integrating Lua – having to manage yet another layer of memory. What I ended up doing was to grab the table reference at game startup and stick it into an index on the stack, and keep around that index. So then, rather than do:

- pop table
- getfield of index -1

I would do:

- getfield of index MUD_TABLE_INDEX (or whatever)

This makes it easier to avoid leaks, and furthermore is slightly faster (because it avoids the table lookup every time you want to do anything).
24 Jan, 2012, Omega wrote in the 5th comment:
Votes: 0
I'm glad you answered back D.H. I was wondering if you have any recommendations for sandboxing the lua state? I've seen several examples, but most are pre-5.2.
24 Jan, 2012, David Haley wrote in the 6th comment:
Votes: 0
What do you mean in this case? I've heard that used to mean a bunch of different things. When I want to sandbox the state, I just make sure it doesn't have access to functions that do things it shouldn't. I know that sounds silly to say but that's really all there is to it. If you want a sandbox on top of the sandbox, then a very useful trick is to run functions or scripts in a function environment. This used to be really, really easy in 5.1 but 5.2 has made it more complicated. You can read a bit about it here:
http://lua-users.org/lists/lua-l/2011-05...

that's the function replacement to create a function environment sandbox.

Basically a function environment is a restriction of the variables that a given function execution can see. It's incredibly useful when you don't feel like creating a whole new state that only contains the stuff you need.

That said, if you have functions for accessing data in C, then you could have an entire Lua state for sandboxed execution that you've set up only with "safe" functions. You could presumably add logic for privileged execution such that if you try to get the function "dangerous_operation", it goes to the metatable and checks if the current context is privileged.
24 Jan, 2012, Omega wrote in the 7th comment:
Votes: 0
Thats pretty much what I needed to hear.

I am running a global lua state, I have all my functions pushed to it, and bound my classes via SLB (Simple Lua Binder).

Most things I believe I can override easily enough. like…

oldprint = print             – point the print function to oldprint
function print(c, str) – replace with new print (for our characters)
– do checks here & then write to the creature.
c:writeBuffer(str)
end


Simply put though, my goal is to ensure that the lua environment is safe from malicious code by builders down the line. Of course, I guess the best case for 100% safety and retain overall functionality/capabilities of lua is to write it myself; or do as you said and do a series of checks to see whether it is allowed execution or not.
24 Jan, 2012, Chris Bailey wrote in the 8th comment:
Votes: 0
If you specify the language in your code tag, you get some fancy smancy syntax highlighting.

bool LuaEngine::runLuaCommand( Creature *c, const std::string &after )
{
bool match = false;
if(!c)
return false;

try {
int top = lua_gettop(mLuaVM);
lua_getglobal(mLuaVM, "sandstorm");
lua_getfield(mLuaVM, -1, "runcommand");
if(!lua_isfunction(mLuaVM, -1))
{
lua_pop(mLuaVM,1);
Log::instance().bug(eLOGLOW, "Warning: Lua script function '%s' does not exist", "sandstorm.runcommand");
return false;
}
SandBind::push<Creature*>(mLuaVM, c);
lua_pushstring( mLuaVM, after.c_str() );

if ( lua_pcall( mLuaVM, 2, 1, 0 ) != 0 )
Log::instance().bug(eLOGLOW, "lua: function 'sandstorm.runcommand': (%s) %s", c->getName().c_str(), lua_tostring( mLuaVM, -1 ) );
if ( !lua_isboolean( mLuaVM, -1 ) )
return false;
match = lua_toboolean( mLuaVM, -1 );
lua_pop( mLuaVM, 1 );
} catch (std::exception &e) {
Log::instance().exception(eLOGLOW, e.what());
} catch (…) {
Log::instance().exception(eLOGLOW, "An unknown error has occured from within runLuaCommand!");
}

return match;
}


edit by kiasyn: changed language from lua to cpp because chris is confused
25 Jan, 2012, Omega wrote in the 9th comment:
Votes: 0
I really liked the edit comment by Kiasyn.
0.0/9