summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-06-21 11:19:35 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-06-21 11:19:35 +0000
commit6e7c6ae56792add3f8d701eca7d144d96ed19458 (patch)
tree855f8b6bcdd61c92be270aa6df1efbad2f603547 /crawl-ref
parentefe55b27c4832476e55ba9100da52daa74fdb75b (diff)
downloadcrawl-ref-6e7c6ae56792add3f8d701eca7d144d96ed19458.tar.gz
crawl-ref-6e7c6ae56792add3f8d701eca7d144d96ed19458.zip
Added support for limiting memory used by the Lua interpreter.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1613 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/AppHdr.h18
-rw-r--r--crawl-ref/source/acr.cc3
-rw-r--r--crawl-ref/source/clua.cc71
-rw-r--r--crawl-ref/source/clua.h7
-rw-r--r--crawl-ref/source/delay.cc2
-rw-r--r--crawl-ref/source/ouch.cc2
6 files changed, 78 insertions, 25 deletions
diff --git a/crawl-ref/source/AppHdr.h b/crawl-ref/source/AppHdr.h
index a42d8141a9..a96eb04111 100644
--- a/crawl-ref/source/AppHdr.h
+++ b/crawl-ref/source/AppHdr.h
@@ -43,17 +43,19 @@
#ifndef APPHDR_H
#define APPHDR_H
-#if defined(GCC)
-# define HASH_CONTAINER_NS __gnu_cxx
-# define HASH_CONTAINERS
-#endif
-
-// Uncomment to enable the Crawl Lua bindings. You can also set this in your
-// makefile by adding -DCLUA_BINDINGS to the CFLAGS line (this is preferred to
-// editing AppHdr.h directly).
+// Uncomment to enable the Crawl Lua bindings. You can also set this
+// in your makefile by adding -DCLUA_BINDINGS to the CFLAGS line (this
+// is preferred to editing AppHdr.h directly).
//
// #define CLUA_BINDINGS
+// The maximum memory that the user-script Lua interpreter can
+// allocate, in kilobytes. This limit is enforced to prevent
+// badly-written or malicious user scripts from consuming too much
+// memory.
+//
+#define CLUA_MAX_MEMORY_USE (2 * 1024)
+
// Enable support for Unicode character glyphs. Note that this needs
// to be accompanied by changes to linker and compiler options and may
// not be available on all platforms. In most cases you want to set
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index 43d2a7933d..9f01b74414 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -297,7 +297,8 @@ int main( int argc, char *argv[] )
simple_god_message( " says: Go forth and aid the weak!" );
break;
case GOD_BEOGH:
- simple_god_message( " says: Let disbelievers drown in blood!" );
+ simple_god_message(
+ " says: Drown the unbelievers in a sea of blood!");
break;
default:
break;
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc
index fb36672fe9..d6ddf14a0b 100644
--- a/crawl-ref/source/clua.cc
+++ b/crawl-ref/source/clua.cc
@@ -11,6 +11,7 @@
#include "chardump.h"
#include "cio.h"
#include "delay.h"
+#include "files.h"
#include "food.h"
#include "invent.h"
#include "initfile.h"
@@ -31,15 +32,7 @@
#include "stuff.h"
#include <cstring>
-
-#ifdef HASH_CONTAINERS
-# include <hash_map>
-# define CHMAP HASH_CONTAINER_NS::hash_map
-#else
-# include <map>
-# define CHMAP std::map
-#endif
-
+#include <map>
#include <cctype>
#define BUGGY_PCALL_ERROR "667: Malformed response to guarded pcall."
@@ -57,23 +50,28 @@
else
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 *);
CLua clua(true);
const int CLua::MAX_THROTTLE_SLEEPS;
CLua::CLua(bool managed)
- : error(), managed_vm(managed), throttle_unit_lines(10000),
+ : error(), managed_vm(managed), shutting_down(false),
+ throttle_unit_lines(10000),
throttle_sleep_ms(0), throttle_sleep_start(2),
throttle_sleep_end(800), n_throttle_sleeps(0), mixed_call_depth(0),
lua_call_depth(0), max_mixed_call_depth(8),
- max_lua_call_depth(100), _state(NULL), sourced_files(), uniqindex(0L)
+ max_lua_call_depth(100), memory_used(0),
+ _state(NULL), sourced_files(), uniqindex(0L)
{
}
CLua::~CLua()
{
+ shutting_down = true;
if (_state)
lua_close(_state);
}
@@ -546,9 +544,12 @@ void CLua::init_lua()
if (_state)
return;
- _state = lua_open();
+ _state = managed_vm? lua_newstate(clua_allocator, this) : luaL_newstate();
if (!_state)
return;
+
+ lua_atpanic(_state, clua_panic);
+
luaopen_base(_state);
luaopen_string(_state);
luaopen_table(_state);
@@ -2168,7 +2169,7 @@ void lua_open_monsters(lua_State *ls)
#define PATTERN_FLUSH_CEILING 100
-typedef CHMAP<std::string, text_pattern> pattern_map;
+typedef std::map<std::string, text_pattern> pattern_map;
static pattern_map pattern_cache;
static text_pattern &get_text_pattern(const std::string &s, bool checkcase)
@@ -2181,7 +2182,7 @@ static text_pattern &get_text_pattern(const std::string &s, bool checkcase)
pattern_cache.clear();
pattern_cache[s] = text_pattern(s, !checkcase);
- return pattern_cache[s];
+ return (pattern_cache[s]);
}
static int lua_pmatch(lua_State *ls)
@@ -2380,6 +2381,48 @@ bool lua_text_pattern::translate() const
lua_call_throttle::lua_clua_map lua_call_throttle::lua_map;
+// A panic function for the Lua interpreter, usually called when it
+// runs out of memory when trying to load a file or a chunk of Lua from
+// an unprotected Lua op. The only cases of unprotected Lua loads are
+// loads of Lua code from .crawlrc, which is read at start of game.
+//
+// If there's an inordinately large .crawlrc (we're talking seriously
+// massive here) that wants more memory than we're willing to give
+// Lua, then the game will save and exit until the .crawlrc is fixed.
+//
+// Lua can also run out of memory during protected script execution,
+// such as when running a macro or some other game hook, but in such
+// cases the Lua interpreter will throw an exception instead of
+// panicking.
+//
+static int clua_panic(lua_State *ls)
+{
+ if (crawl_state.need_save && !crawl_state.saving_game
+ && !crawl_state.updating_scores)
+ {
+ save_game(true);
+ }
+ return (0);
+}
+
+static void *clua_allocator(void *ud, void *ptr, size_t osize, size_t nsize)
+{
+ CLua *cl = static_cast<CLua *>( ud );
+ cl->memory_used += nsize - osize;
+
+ if (nsize > osize && cl->memory_used >= CLUA_MAX_MEMORY_USE * 1024
+ && cl->mixed_call_depth)
+ return (NULL);
+
+ if (!nsize)
+ {
+ free(ptr);
+ return (NULL);
+ }
+ else
+ return (realloc(ptr, nsize));
+}
+
static void clua_throttle_hook(lua_State *ls, lua_Debug *dbg)
{
CLua *lua = lua_call_throttle::find_clua(ls);
diff --git a/crawl-ref/source/clua.h b/crawl-ref/source/clua.h
index af6196f826..a060923da7 100644
--- a/crawl-ref/source/clua.h
+++ b/crawl-ref/source/clua.h
@@ -18,6 +18,10 @@ extern "C" {
#include "libutil.h"
#include "externs.h"
+#ifndef CLUA_MAX_MEMORY_USE
+#define CLUA_MAX_MEMORY_USE (6 * 1024)
+#endif
+
class CLua;
class lua_call_throttle
{
@@ -76,6 +80,7 @@ public:
// If managed_vm is set, we have to take steps to control badly-behaved
// scripts.
bool managed_vm;
+ bool shutting_down;
int throttle_unit_lines;
int throttle_sleep_ms;
int throttle_sleep_start, throttle_sleep_end;
@@ -85,6 +90,8 @@ public:
int max_mixed_call_depth;
int max_lua_call_depth;
+ long memory_used;
+
static const int MAX_THROTTLE_SLEEPS = 100;
private:
diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc
index a993b30b71..f8f5806705 100644
--- a/crawl-ref/source/delay.cc
+++ b/crawl-ref/source/delay.cc
@@ -873,7 +873,7 @@ void run_macro(const char *macroname)
if (!clua.callbooleanfn(false, "c_macro", "s", macroname))
{
if (clua.error.length())
- mpr(clua.error.c_str());
+ mprf(MSGCH_WARN, "Lua error: %s", clua.error.c_str());
stop_delay();
}
diff --git a/crawl-ref/source/ouch.cc b/crawl-ref/source/ouch.cc
index 77b3ee92d3..06c3b9fefb 100644
--- a/crawl-ref/source/ouch.cc
+++ b/crawl-ref/source/ouch.cc
@@ -736,7 +736,7 @@ void ouch( int dam, int death_source, kill_method_type death_type,
interrupt_activity( AI_HP_LOSS, &hpl );
if (you.deaths_door && death_type != KILLED_BY_LAVA
- && death_type != KILLED_BY_WATER)
+ && death_type != KILLED_BY_WATER)
{
return;
}