diff options
author | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2007-06-21 13:17:24 +0000 |
---|---|---|
committer | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2007-06-21 13:17:24 +0000 |
commit | 9f969702ad3564f95eb20fe25950981bc7028851 (patch) | |
tree | dca7d6f8d55b1771fd66b3c0bd8f698ee25d7b05 /crawl-ref/source/clua.cc | |
parent | 6e7c6ae56792add3f8d701eca7d144d96ed19458 (diff) | |
download | crawl-ref-9f969702ad3564f95eb20fe25950981bc7028851.tar.gz crawl-ref-9f969702ad3564f95eb20fe25950981bc7028851.zip |
Override loadfile and dofile in the Lua user-script interpreter so they have to
use datafile_path, and cannot use shell metacharacters (not that it matters)
and ../ paths. Multiple loading is not prevented; we could probably add another
function that does that.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1614 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/clua.cc')
-rw-r--r-- | crawl-ref/source/clua.cc | 112 |
1 files changed, 75 insertions, 37 deletions
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc index d6ddf14a0b..5953355df2 100644 --- a/crawl-ref/source/clua.cc +++ b/crawl-ref/source/clua.cc @@ -49,10 +49,12 @@ } \ else +static int clua_panic(lua_State *); static void clua_throttle_hook(lua_State *, lua_Debug *); static void *clua_allocator(void *ud, void *ptr, size_t osize, size_t nsize); static int clua_guarded_pcall(lua_State *); -static int clua_panic(lua_State *); +static int clua_dofile(lua_State *); +static int clua_loadfile(lua_State *); CLua clua(true); @@ -214,6 +216,28 @@ int CLua::execstring(const char *s, const char *context) return err; } +bool CLua::is_path_safe(const char *s) +{ + return (!strstr(s, "..") && shell_safe(s)); +} + +int CLua::loadfile(lua_State *ls, const char *filename) +{ + if (!ls) + return (-1); + + if (!is_path_safe(filename)) + { + lua_pushstring( + ls, + make_stringf("invalid filename: %s", filename).c_str()); + return (-1); + } + + const std::string file = datafile_path(filename, false); + return (luaL_loadfile(ls, file.c_str())); +} + int CLua::execfile(const char *filename) { if (sourced_files.find(filename) != sourced_files.end()) @@ -221,20 +245,8 @@ int CLua::execfile(const char *filename) sourced_files.insert(filename); - FILE *f = fopen(filename, "r"); - if (f) - fclose(f); - else - { - error = std::string("Can't read ") + filename; - return -1; - } - lua_State *ls = state(); - if (!ls) - return -1; - - int err = luaL_loadfile(ls, filename); + int err = loadfile(ls, filename); lua_call_throttle strangler(this); if (!err) err = lua_pcall(ls, 0, 0, 0); @@ -570,16 +582,11 @@ void CLua::init_lua() load_chooks(); if (managed_vm) - guard_pcall(); -} - -void CLua::guard_pcall() -{ - // Replace Lua's pcall() with our own version which doesn't swallow - // 666: errors that we generate for buggy or malicious scripts that try - // to hog CPU. - - lua_register(_state, "pcall", clua_guarded_pcall); + { + lua_register(_state, "pcall", clua_guarded_pcall); + lua_register(_state, "loadfile", clua_loadfile); + lua_register(_state, "dofile", clua_dofile); + } } void CLua::load_chooks() @@ -2452,6 +2459,26 @@ static void clua_throttle_hook(lua_State *ls, lua_Debug *dbg) } } +lua_call_throttle::lua_call_throttle(CLua *_lua) + : lua(_lua) +{ + lua->init_throttle(); + if (!lua->mixed_call_depth++) + lua_map[lua->state()] = lua; +} + +lua_call_throttle::~lua_call_throttle() +{ + if (!--lua->mixed_call_depth) + lua_map.erase(lua->state()); +} + +CLua *lua_call_throttle::find_clua(lua_State *ls) +{ + lua_clua_map::iterator i = lua_map.find(ls); + return (i != lua_map.end()? i->second : NULL); +} + // This function is a replacement for Lua's in-built pcall function. It behaves // like pcall in all respects (as documented in the Lua 5.1 reference manual), // but does not allow the Lua chunk/script to catch errors thrown by the @@ -2488,22 +2515,33 @@ static int clua_guarded_pcall(lua_State *ls) return (lua_gettop(ls)); } -lua_call_throttle::lua_call_throttle(CLua *_lua) - : lua(_lua) +static int clua_loadfile(lua_State *ls) { - lua->init_throttle(); - if (!lua->mixed_call_depth++) - lua_map[lua->state()] = lua; -} + const char *file = luaL_checkstring(ls, 1); + if (!file) + return (0); -lua_call_throttle::~lua_call_throttle() -{ - if (!--lua->mixed_call_depth) - lua_map.erase(lua->state()); + const int err = CLua::loadfile(ls, file); + if (err) + { + const int place = lua_gettop(ls); + lua_pushnil(ls); + lua_insert(ls, place); + return (2); + } + return (1); } -CLua *lua_call_throttle::find_clua(lua_State *ls) +static int clua_dofile(lua_State *ls) { - lua_clua_map::iterator i = lua_map.find(ls); - return (i != lua_map.end()? i->second : NULL); + const char *file = luaL_checkstring(ls, 1); + if (!file) + return (0); + + const int err = CLua::loadfile(ls, file); + if (err) + return (lua_error(ls)); + + lua_call(ls, 0, LUA_MULTRET); + return (lua_gettop(ls)); } |