diff --git a/src/blua/liolib.c b/src/blua/liolib.c index e029650c0..545f9c144 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -24,12 +24,14 @@ #include "../byteptr.h" #include "../lua_script.h" #include "../m_misc.h" +#include "../i_time.h" #define IO_INPUT 1 #define IO_OUTPUT 2 -#define FILELIMIT (1024 * 1024) // Size limit for reading/writing files +#define MAXBYTESPERMINUTE (10 * 1024 * 1024) // Rate limit for writing files +#define MAXOPENSPERMINUTE 50 // Rate limit for opening new files #define FMT_FILECALLBACKID "file_callback_%d" @@ -46,6 +48,10 @@ static const char *whitelist[] = { }; +static INT64 numwrittenbytes = 0; +static INT64 numopenedfiles = 0; + + static int pushresult (lua_State *L, int i, const char *filename) { int en = errno; /* calls to Lua API may change this value */ if (i) { @@ -252,6 +258,17 @@ static int io_openlocal (lua_State *L) { "Files can't be opened while being downloaded\n", filename); + // Reading not restricted + if (client && (strchr(mode, 'w') || strchr(mode, 'a') || strchr(mode, '+'))) + { + if (numopenedfiles >= (I_GetTime() / (60*TICRATE) + 1) * MAXOPENSPERMINUTE) + I_Error("Access denied to %s\n" + "File opening rate exceeded\n", + filename); + + numopenedfiles++; + } + MakePathDirs(realfilename); // Open and return the file @@ -527,9 +544,12 @@ static int g_write (lua_State *L, FILE *f, int arg) { else { size_t l; const char *s = luaL_checklstring(L, arg, &l); - if (ftell(f) + l > FILELIMIT) { - luaL_error(L,"write limit bypassed in file. Changes have been discarded."); - break; + if (client) { + if (numwrittenbytes + l > (I_GetTime() / (60*TICRATE) + 1) * MAXBYTESPERMINUTE) { + luaL_error(L,"file write rate limit exceeded; changes have been discarded"); + break; + } + numwrittenbytes += l; } status = status && (fwrite(s, sizeof(char), l, f) == l); } diff --git a/src/i_time.c b/src/i_time.c index 55d1557bd..2a22503f1 100644 --- a/src/i_time.c +++ b/src/i_time.c @@ -43,18 +43,20 @@ tic_t I_GetTime(void) void I_InitializeTime(void) { - g_time.time = 0; - g_time.timefrac = 0; - - enterprecise = 0; - oldenterprecise = 0; - tictimer = 0.0; - CV_RegisterVar(&cv_timescale); // I_StartupTimer is preserved for potential subsystems that need to setup // timing information for I_GetPreciseTime and sleeping I_StartupTimer(); + + g_time.time = 0; + g_time.timefrac = 0; + + enterprecise = I_GetPreciseTime(); + oldenterprecise = enterprecise; + entertic = 0; + oldentertics = 0; + tictimer = 0.0; } void I_UpdateTime(fixed_t timescale)