From eb7c36d72c04628aacea18c79dc95e87fc1a7581 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Sat, 16 Jan 2016 19:31:36 -0600 Subject: [PATCH 01/20] Reimplement I/O library Note: I/O library is fully functioning in this state, but lacks security restrictions. We'll get to those later ;) --- src/blua/Makefile.cfg | 1 + src/blua/linit.c | 1 + src/blua/liolib.c | 553 ++++++++++++++++++++++++++++++++++++++++++ src/blua/lualib.h | 3 + 4 files changed, 558 insertions(+) create mode 100644 src/blua/liolib.c diff --git a/src/blua/Makefile.cfg b/src/blua/Makefile.cfg index e3fb3df4..895f9362 100644 --- a/src/blua/Makefile.cfg +++ b/src/blua/Makefile.cfg @@ -18,6 +18,7 @@ OBJS:=$(OBJS) \ $(OBJDIR)/ldo.o \ $(OBJDIR)/lfunc.o \ $(OBJDIR)/linit.o \ + $(OBJDIR)/liolib.o \ $(OBJDIR)/llex.o \ $(OBJDIR)/lmem.o \ $(OBJDIR)/lobject.o \ diff --git a/src/blua/linit.c b/src/blua/linit.c index 52b02dbe..d17390b2 100644 --- a/src/blua/linit.c +++ b/src/blua/linit.c @@ -17,6 +17,7 @@ static const luaL_Reg lualibs[] = { {"", luaopen_base}, {LUA_TABLIBNAME, luaopen_table}, + {LUA_IOLIBNAME, luaopen_io}, {LUA_STRLIBNAME, luaopen_string}, {NULL, NULL} }; diff --git a/src/blua/liolib.c b/src/blua/liolib.c new file mode 100644 index 00000000..e79ed1cb --- /dev/null +++ b/src/blua/liolib.c @@ -0,0 +1,553 @@ +/* +** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $ +** Standard I/O (and system) library +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include + +#define liolib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +#define IO_INPUT 1 +#define IO_OUTPUT 2 + + +static const char *const fnames[] = {"input", "output"}; + + +static int pushresult (lua_State *L, int i, const char *filename) { + int en = errno; /* calls to Lua API may change this value */ + if (i) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + if (filename) + lua_pushfstring(L, "%s: %s", filename, strerror(en)); + else + lua_pushfstring(L, "%s", strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} + + +static void fileerror (lua_State *L, int arg, const char *filename) { + lua_pushfstring(L, "%s: %s", filename, strerror(errno)); + luaL_argerror(L, arg, lua_tostring(L, -1)); +} + + +#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) + + +static int io_type (lua_State *L) { + void *ud; + luaL_checkany(L, 1); + ud = lua_touserdata(L, 1); + lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); + if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) + lua_pushnil(L); /* not a file */ + else if (*((FILE **)ud) == NULL) + lua_pushliteral(L, "closed file"); + else + lua_pushliteral(L, "file"); + return 1; +} + + +static FILE *tofile (lua_State *L) { + FILE **f = tofilep(L); + if (*f == NULL) + luaL_error(L, "attempt to use a closed file"); + return *f; +} + + + +/* +** When creating file handles, always creates a `closed' file handle +** before opening the actual file; so, if there is a memory error, the +** file is not left opened. +*/ +static FILE **newfile (lua_State *L) { + FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); + *pf = NULL; /* file handle is currently `closed' */ + luaL_getmetatable(L, LUA_FILEHANDLE); + lua_setmetatable(L, -2); + return pf; +} + + +/* +** function to (not) close the standard files stdin, stdout, and stderr +*/ +static int io_noclose (lua_State *L) { + lua_pushnil(L); + lua_pushliteral(L, "cannot close standard file"); + return 2; +} + + +/* +** function to close 'popen' files +*/ +static int io_pclose (lua_State *L) { + FILE **p = tofilep(L); + int ok = lua_pclose(L, *p); + *p = NULL; + return pushresult(L, ok, NULL); +} + + +/* +** function to close regular files +*/ +static int io_fclose (lua_State *L) { + FILE **p = tofilep(L); + int ok = (fclose(*p) == 0); + *p = NULL; + return pushresult(L, ok, NULL); +} + + +static int aux_close (lua_State *L) { + lua_getfenv(L, 1); + lua_getfield(L, -1, "__close"); + return (lua_tocfunction(L, -1))(L); +} + + +static int io_close (lua_State *L) { + if (lua_isnone(L, 1)) + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); + tofile(L); /* make sure argument is a file */ + return aux_close(L); +} + + +static int io_gc (lua_State *L) { + FILE *f = *tofilep(L); + /* ignore closed files */ + if (f != NULL) + aux_close(L); + return 0; +} + + +static int io_tostring (lua_State *L) { + FILE *f = *tofilep(L); + if (f == NULL) + lua_pushliteral(L, "file (closed)"); + else + lua_pushfstring(L, "file (%p)", f); + return 1; +} + + +static int io_open (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +} + + +/* +** this function has a separated environment, which defines the +** correct __close for 'popen' files +*/ +static int io_popen (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = lua_popen(L, filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +} + + +static int io_tmpfile (lua_State *L) { + FILE **pf = newfile(L); + *pf = tmpfile(); + return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; +} + + +static FILE *getiofile (lua_State *L, int findex) { + FILE *f; + lua_rawgeti(L, LUA_ENVIRONINDEX, findex); + f = *(FILE **)lua_touserdata(L, -1); + if (f == NULL) + luaL_error(L, "standard %s file is closed", fnames[findex - 1]); + return f; +} + + +static int g_iofile (lua_State *L, int f, const char *mode) { + if (!lua_isnoneornil(L, 1)) { + const char *filename = lua_tostring(L, 1); + if (filename) { + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + if (*pf == NULL) + fileerror(L, 1, filename); + } + else { + tofile(L); /* check that it's a valid file handle */ + lua_pushvalue(L, 1); + } + lua_rawseti(L, LUA_ENVIRONINDEX, f); + } + /* return current value */ + lua_rawgeti(L, LUA_ENVIRONINDEX, f); + return 1; +} + + +static int io_input (lua_State *L) { + return g_iofile(L, IO_INPUT, "r"); +} + + +static int io_output (lua_State *L) { + return g_iofile(L, IO_OUTPUT, "w"); +} + + +static int io_readline (lua_State *L); + + +static void aux_lines (lua_State *L, int idx, int toclose) { + lua_pushvalue(L, idx); + lua_pushboolean(L, toclose); /* close/not close file when finished */ + lua_pushcclosure(L, io_readline, 2); +} + + +static int f_lines (lua_State *L) { + tofile(L); /* check that it's a valid file handle */ + aux_lines(L, 1, 0); + return 1; +} + + +static int io_lines (lua_State *L) { + if (lua_isnoneornil(L, 1)) { /* no arguments? */ + /* will iterate over default input */ + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); + return f_lines(L); + } + else { + const char *filename = luaL_checkstring(L, 1); + FILE **pf = newfile(L); + *pf = fopen(filename, "r"); + if (*pf == NULL) + fileerror(L, 1, filename); + aux_lines(L, lua_gettop(L), 1); + return 1; + } +} + + +/* +** {====================================================== +** READ +** ======================================================= +*/ + + +static int read_number (lua_State *L, FILE *f) { + lua_Number d; + if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { + lua_pushnumber(L, d); + return 1; + } + else return 0; /* read fails */ +} + + +static int test_eof (lua_State *L, FILE *f) { + int c = getc(f); + ungetc(c, f); + lua_pushlstring(L, NULL, 0); + return (c != EOF); +} + + +static int read_line (lua_State *L, FILE *f) { + luaL_Buffer b; + luaL_buffinit(L, &b); + for (;;) { + size_t l; + char *p = luaL_prepbuffer(&b); + if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ + luaL_pushresult(&b); /* close buffer */ + return (lua_objlen(L, -1) > 0); /* check whether read something */ + } + l = strlen(p); + if (l == 0 || p[l-1] != '\n') + luaL_addsize(&b, l); + else { + luaL_addsize(&b, l - 1); /* do not include `eol' */ + luaL_pushresult(&b); /* close buffer */ + return 1; /* read at least an `eol' */ + } + } +} + + +static int read_chars (lua_State *L, FILE *f, size_t n) { + size_t rlen; /* how much to read */ + size_t nr; /* number of chars actually read */ + luaL_Buffer b; + luaL_buffinit(L, &b); + rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ + do { + char *p = luaL_prepbuffer(&b); + if (rlen > n) rlen = n; /* cannot read more than asked */ + nr = fread(p, sizeof(char), rlen, f); + luaL_addsize(&b, nr); + n -= nr; /* still have to read `n' chars */ + } while (n > 0 && nr == rlen); /* until end of count or eof */ + luaL_pushresult(&b); /* close buffer */ + return (n == 0 || lua_objlen(L, -1) > 0); +} + + +static int g_read (lua_State *L, FILE *f, int first) { + int nargs = lua_gettop(L) - 1; + int success; + int n; + clearerr(f); + if (nargs == 0) { /* no arguments? */ + success = read_line(L, f); + n = first+1; /* to return 1 result */ + } + else { /* ensure stack space for all results and for auxlib's buffer */ + luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); + success = 1; + for (n = first; nargs-- && success; n++) { + if (lua_type(L, n) == LUA_TNUMBER) { + size_t l = (size_t)lua_tointeger(L, n); + success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); + } + else { + const char *p = lua_tostring(L, n); + luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); + switch (p[1]) { + case 'n': /* number */ + success = read_number(L, f); + break; + case 'l': /* line */ + success = read_line(L, f); + break; + case 'a': /* file */ + read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ + success = 1; /* always success */ + break; + default: + return luaL_argerror(L, n, "invalid format"); + } + } + } + } + if (ferror(f)) + return pushresult(L, 0, NULL); + if (!success) { + lua_pop(L, 1); /* remove last result */ + lua_pushnil(L); /* push nil instead */ + } + return n - first; +} + + +static int io_read (lua_State *L) { + return g_read(L, getiofile(L, IO_INPUT), 1); +} + + +static int f_read (lua_State *L) { + return g_read(L, tofile(L), 2); +} + + +static int io_readline (lua_State *L) { + FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1)); + int sucess; + if (f == NULL) /* file is already closed? */ + luaL_error(L, "file is already closed"); + sucess = read_line(L, f); + if (ferror(f)) + return luaL_error(L, "%s", strerror(errno)); + if (sucess) return 1; + else { /* EOF */ + if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ + lua_settop(L, 0); + lua_pushvalue(L, lua_upvalueindex(1)); + aux_close(L); /* close it */ + } + return 0; + } +} + +/* }====================================================== */ + + +static int g_write (lua_State *L, FILE *f, int arg) { + int nargs = lua_gettop(L) - 1; + int status = 1; + for (; nargs--; arg++) { + if (lua_type(L, arg) == LUA_TNUMBER) { + /* optimization: could be done exactly as for strings */ + status = status && + fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; + } + else { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + status = status && (fwrite(s, sizeof(char), l, f) == l); + } + } + return pushresult(L, status, NULL); +} + + +static int io_write (lua_State *L) { + return g_write(L, getiofile(L, IO_OUTPUT), 1); +} + + +static int f_write (lua_State *L) { + return g_write(L, tofile(L), 2); +} + + +static int f_seek (lua_State *L) { + static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; + static const char *const modenames[] = {"set", "cur", "end", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, "cur", modenames); + long offset = luaL_optlong(L, 3, 0); + op = fseek(f, offset, mode[op]); + if (op) + return pushresult(L, 0, NULL); /* error */ + else { + lua_pushinteger(L, ftell(f)); + return 1; + } +} + + +static int f_setvbuf (lua_State *L) { + static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; + static const char *const modenames[] = {"no", "full", "line", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, NULL, modenames); + lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); + int res = setvbuf(f, NULL, mode[op], sz); + return pushresult(L, res == 0, NULL); +} + + + +static int io_flush (lua_State *L) { + return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); +} + + +static int f_flush (lua_State *L) { + return pushresult(L, fflush(tofile(L)) == 0, NULL); +} + + +static const luaL_Reg iolib[] = { + {"close", io_close}, + {"flush", io_flush}, + {"input", io_input}, + {"lines", io_lines}, + {"open", io_open}, + {"output", io_output}, + {"popen", io_popen}, + {"read", io_read}, + {"tmpfile", io_tmpfile}, + {"type", io_type}, + {"write", io_write}, + {NULL, NULL} +}; + + +static const luaL_Reg flib[] = { + {"close", io_close}, + {"flush", f_flush}, + {"lines", f_lines}, + {"read", f_read}, + {"seek", f_seek}, + {"setvbuf", f_setvbuf}, + {"write", f_write}, + {"__gc", io_gc}, + {"__tostring", io_tostring}, + {NULL, NULL} +}; + + +static void createmeta (lua_State *L) { + luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_register(L, NULL, flib); /* file methods */ +} + + +static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { + *newfile(L) = f; + if (k > 0) { + lua_pushvalue(L, -1); + lua_rawseti(L, LUA_ENVIRONINDEX, k); + } + lua_pushvalue(L, -2); /* copy environment */ + lua_setfenv(L, -2); /* set it */ + lua_setfield(L, -3, fname); +} + + +static void newfenv (lua_State *L, lua_CFunction cls) { + lua_createtable(L, 0, 1); + lua_pushcfunction(L, cls); + lua_setfield(L, -2, "__close"); +} + + +LUALIB_API int luaopen_io (lua_State *L) { + createmeta(L); + /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ + newfenv(L, io_fclose); + lua_replace(L, LUA_ENVIRONINDEX); + /* open library */ + luaL_register(L, LUA_IOLIBNAME, iolib); + /* create (and set) default files */ + newfenv(L, io_noclose); /* close function for default files */ + createstdfile(L, stdin, IO_INPUT, "stdin"); + createstdfile(L, stdout, IO_OUTPUT, "stdout"); + createstdfile(L, stderr, 0, "stderr"); + lua_pop(L, 1); /* pop environment for default files */ + lua_getfield(L, -1, "popen"); + newfenv(L, io_pclose); /* create environment for 'popen' */ + lua_setfenv(L, -2); /* set fenv for 'popen' */ + lua_pop(L, 1); /* pop 'popen' */ + return 1; +} + diff --git a/src/blua/lualib.h b/src/blua/lualib.h index 6ebe2728..4ea97edf 100644 --- a/src/blua/lualib.h +++ b/src/blua/lualib.h @@ -21,6 +21,9 @@ LUALIB_API int (luaopen_base) (lua_State *L); #define LUA_TABLIBNAME "table" LUALIB_API int (luaopen_table) (lua_State *L); +#define LUA_IOLIBNAME "io" +LUALIB_API int (luaopen_io) (lua_State *L); + #define LUA_STRLIBNAME "string" LUALIB_API int (luaopen_string) (lua_State *L); From c9fe83b95daa3189465049e53c058bdfa1ce51b4 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Sun, 17 Jan 2016 01:37:19 -0600 Subject: [PATCH 02/20] Block the use of ../ and ..\\ ...and remove io.popen(), cause that shit is DANGEROUS. --- src/blua/liolib.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index e79ed1cb..5c48add7 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -160,6 +160,11 @@ static int io_tostring (lua_State *L) { static int io_open (lua_State *L) { const char *filename = luaL_checkstring(L, 1); + if (strstr(filename, "../") || strstr(filename, "..\\")) + { + luaL_error(L,"access denied to %s", filename); + return pushresult(L,0,filename); + } const char *mode = luaL_optstring(L, 2, "r"); FILE **pf = newfile(L); *pf = fopen(filename, mode); @@ -167,19 +172,6 @@ static int io_open (lua_State *L) { } -/* -** this function has a separated environment, which defines the -** correct __close for 'popen' files -*/ -static int io_popen (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - FILE **pf = newfile(L); - *pf = lua_popen(L, filename, mode); - return (*pf == NULL) ? pushresult(L, 0, filename) : 1; -} - - static int io_tmpfile (lua_State *L) { FILE **pf = newfile(L); *pf = tmpfile(); @@ -481,7 +473,6 @@ static const luaL_Reg iolib[] = { {"lines", io_lines}, {"open", io_open}, {"output", io_output}, - {"popen", io_popen}, {"read", io_read}, {"tmpfile", io_tmpfile}, {"type", io_type}, From a68e92690f8cc176e0c0e92b73e9c38ead20d3b3 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Wed, 20 Jan 2016 02:26:15 -0600 Subject: [PATCH 03/20] Implement file type whitelist, completely remove popen and pclose This is probably super inefficient. Someone please teach me how2C. --- src/blua/liolib.c | 52 ++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index 5c48add7..d2303415 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -25,6 +25,13 @@ static const char *const fnames[] = {"input", "output"}; +static const char *whitelist[] = { // Allow scripters to write files of these types to SRB2's folder + ".txt", + ".sav2", + ".cfg", + ".png", + ".bmp" +}; static int pushresult (lua_State *L, int i, const char *filename) { @@ -102,17 +109,6 @@ static int io_noclose (lua_State *L) { } -/* -** function to close 'popen' files -*/ -static int io_pclose (lua_State *L) { - FILE **p = tofilep(L); - int ok = lua_pclose(L, *p); - *p = NULL; - return pushresult(L, ok, NULL); -} - - /* ** function to close regular files */ @@ -159,16 +155,26 @@ static int io_tostring (lua_State *L) { static int io_open (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - if (strstr(filename, "../") || strstr(filename, "..\\")) - { - luaL_error(L,"access denied to %s", filename); - return pushresult(L,0,filename); - } - const char *mode = luaL_optstring(L, 2, "r"); - FILE **pf = newfile(L); - *pf = fopen(filename, mode); - return (*pf == NULL) ? pushresult(L, 0, filename) : 1; + const char *filename = luaL_checkstring(L, 1); + int pass = 0; int i; + int length = strlen(filename) - 1; + for (i = 0; i < 5; i++) // wolfs == noobcoder, so manually change this with any added file types + { + if (!stricmp(&filename[length - (strlen(whitelist[i]) - 1)], whitelist[i])) + { + pass = 1; + break; + } + } + if (strstr(filename, "../") || strstr(filename, "..\\") || !pass) + { + luaL_error(L,"access denied to %s", filename); + return pushresult(L,0,filename); + } + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; } @@ -535,10 +541,6 @@ LUALIB_API int luaopen_io (lua_State *L) { createstdfile(L, stdout, IO_OUTPUT, "stdout"); createstdfile(L, stderr, 0, "stderr"); lua_pop(L, 1); /* pop environment for default files */ - lua_getfield(L, -1, "popen"); - newfenv(L, io_pclose); /* create environment for 'popen' */ - lua_setfenv(L, -2); /* set fenv for 'popen' */ - lua_pop(L, 1); /* pop 'popen' */ return 1; } From 569f7d15d1992a437ad48a881feb62ec80d936bd Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Wed, 20 Jan 2016 16:59:55 -0600 Subject: [PATCH 04/20] Efficiency improvement in whitelist check Thanks Inu! --- src/blua/liolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index d2303415..6dd87704 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -158,7 +158,7 @@ static int io_open (lua_State *L) { const char *filename = luaL_checkstring(L, 1); int pass = 0; int i; int length = strlen(filename) - 1; - for (i = 0; i < 5; i++) // wolfs == noobcoder, so manually change this with any added file types + for (i = 0; i < (sizeof (whitelist) / sizeof(const char *)); i++) { if (!stricmp(&filename[length - (strlen(whitelist[i]) - 1)], whitelist[i])) { From de03db99e7110b65190d6d3fe540dfed623b33f2 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Wed, 20 Jan 2016 21:31:00 -0600 Subject: [PATCH 05/20] Block possible methods of accessing folders outside of SRB2 --- src/blua/liolib.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index 6dd87704..100dbb6c 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -153,6 +153,12 @@ static int io_tostring (lua_State *L) { return 1; } +static int StartsWith(const char *a, const char *b) // this is wolfs being lazy yet again +{ + if(strncmp(a, b, strlen(b)) == 0) return 1; + return 0; +} + static int io_open (lua_State *L) { const char *filename = luaL_checkstring(L, 1); @@ -166,7 +172,8 @@ static int io_open (lua_State *L) { break; } } - if (strstr(filename, "../") || strstr(filename, "..\\") || !pass) + if (strstr(filename, "..") || strchr(filename, ':') || StartsWith(filename, "\\") + || StartsWith(filename, "/") || !pass) { luaL_error(L,"access denied to %s", filename); return pushresult(L,0,filename); From 5579fb5240347ddc86987a8aedbae20d8602c4bd Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Wed, 20 Jan 2016 22:35:53 -0600 Subject: [PATCH 06/20] Limit file creation/manipulation to luafiles subfolder Also block % in filename strings --- src/blua/liolib.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index 100dbb6c..ac168ef1 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -17,6 +17,9 @@ #include "lauxlib.h" #include "lualib.h" +#include "../i_system.h" +#include "../doomdef.h" +#include "../m_misc.h" @@ -173,11 +176,14 @@ static int io_open (lua_State *L) { } } if (strstr(filename, "..") || strchr(filename, ':') || StartsWith(filename, "\\") - || StartsWith(filename, "/") || !pass) + || StartsWith(filename, "/") || strchr(filename, '%') || !pass) { luaL_error(L,"access denied to %s", filename); return pushresult(L,0,filename); } + I_mkdir("luafiles", 0755); + char* destFilename = va("luafiles"PATHSEP"%s", filename); + filename = destFilename; const char *mode = luaL_optstring(L, 2, "r"); FILE **pf = newfile(L); *pf = fopen(filename, mode); From e27494652850945f8e69383b8c726639cb4a54dd Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Fri, 22 Jan 2016 00:46:32 -0600 Subject: [PATCH 07/20] Call I_mkdir on subdirectories [NEEDS CLEANUP] I got lazy and used a weird inefficient method, but I don't know how to clean this mess up :c At least it works. --- src/blua/liolib.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index ac168ef1..b209eec9 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -182,6 +182,22 @@ static int io_open (lua_State *L) { return pushresult(L,0,filename); } I_mkdir("luafiles", 0755); + char *splitter = filename; + while ((splitter = strchr(splitter, '/'))) + { + *splitter = 0; + I_mkdir(va("luafiles"PATHSEP"%s", filename), 0755); + *splitter = '/'; + splitter++; + } + char *splitter2 = filename; + while ((splitter2 = strchr(splitter2, '\\'))) + { + *splitter2 = 0; + I_mkdir(va("luafiles"PATHSEP"%s", filename), 0755); + *splitter2 = '\\'; + splitter2++; + } char* destFilename = va("luafiles"PATHSEP"%s", filename); filename = destFilename; const char *mode = luaL_optstring(L, 2, "r"); From 591b8035663fc60490229b63b4c43f55b0c0a81c Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Fri, 22 Jan 2016 21:45:48 -0600 Subject: [PATCH 08/20] Limit file write size to 1MB If the total file size is above 1MB after writing, discard all changes. --- src/blua/liolib.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index b209eec9..2d20f529 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -26,6 +26,8 @@ #define IO_INPUT 1 #define IO_OUTPUT 2 +#define FILELIMIT 1024*1024 // Size limit for reading/writing files + static const char *const fnames[] = {"input", "output"}; static const char *whitelist[] = { // Allow scripters to write files of these types to SRB2's folder @@ -437,6 +439,7 @@ static int io_readline (lua_State *L) { static int g_write (lua_State *L, FILE *f, int arg) { int nargs = lua_gettop(L) - 1; int status = 1; + size_t count; for (; nargs--; arg++) { if (lua_type(L, arg) == LUA_TNUMBER) { /* optimization: could be done exactly as for strings */ @@ -446,6 +449,12 @@ static int g_write (lua_State *L, FILE *f, int arg) { else { size_t l; const char *s = luaL_checklstring(L, arg, &l); + count += l; + if (ftell(f) + l > FILELIMIT) + { + luaL_error(L,"write limit bypassed in file. Changes have been discarded."); + break; + } status = status && (fwrite(s, sizeof(char), l, f) == l); } } From 2639bf4c0ba035bcd79f12ae4f6f00d86feeb662 Mon Sep 17 00:00:00 2001 From: Nipples the Enchilada Date: Sun, 24 Jan 2016 00:24:26 -0500 Subject: [PATCH 09/20] Add liolib.c to CMakeLists --- src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bb4f9a4a..9a8b3bac 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -265,6 +265,7 @@ if(${SRB2_CONFIG_HAVE_BLUA}) blua/lfunc.c blua/lgc.c blua/linit.c + blua/liolib.c blua/llex.c blua/lmem.c blua/lobject.c From 0f2a0927418334376a1675590ba7313dde44606e Mon Sep 17 00:00:00 2001 From: Inuyasha Date: Wed, 20 Jan 2016 01:13:21 -0800 Subject: [PATCH 10/20] objectplace stability fix Objectplace reallocates the mapthings list to add one more mapthing. By itself there's no problem with this. But, mobj->spawnpoint is a pointer to the mapthing's location in the mapthings list. So by reallocating the mapthings list, all references to mobj->spawnpoints point to freed memory. ... Oops. Now when objectplace reallocates the mapthings list it actually corrects the locations of all mobj's spawnpoints to point to the new list. Hooray, you can use NiGHTS objectplace again if you really want to. --- src/m_cheat.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/m_cheat.c b/src/m_cheat.c index bc32e6cf..473fbbf7 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -880,12 +880,33 @@ static boolean OP_HeightOkay(player_t *player, UINT8 ceiling) static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean ceiling) { - mapthing_t *mt; + mapthing_t *mt = mapthings; + #ifdef HAVE_BLUA LUA_InvalidateMapthings(); #endif mapthings = Z_Realloc(mapthings, ++nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); + + // as Z_Realloc can relocate mapthings, quickly go through thinker list and correct + // the spawnpoints of any objects that have them to the new location + if (mt != mapthings) + { + thinker_t *th; + mobj_t *mo; + + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo = (mobj_t *)th; + // get offset from mt, which points to old mapthings, then add new location + if (mo->spawnpoint) + mo->spawnpoint = (mo->spawnpoint - mt) + mapthings; + } + } + mt = (mapthings+nummapthings-1); mt->type = type; From f2f8906a19cd17163853f402f828f609df4c8069 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 18 Jan 2016 19:46:00 +0000 Subject: [PATCH 11/20] Use modulo, not bitwise AND. My fault once again, whoops. The point here is ColorOpposite(MAXSKINCOLORS) would have given an actual result of its own since MAXSKINCOLORS & MAXSKINCOLORS is still MAXSKINCOLORS. This shouldn't happen though, as both Color_Opposite[MAXSKINCOLORS*2] and Color_Opposite[MAXSKINCOLOR*2+1] aren't defined. --- src/lua_mathlib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_mathlib.c b/src/lua_mathlib.c index f4b5ca5f..fd00180d 100644 --- a/src/lua_mathlib.c +++ b/src/lua_mathlib.c @@ -166,7 +166,7 @@ static int lib_all7emeralds(lua_State *L) // Returns both color and frame numbers! static int lib_coloropposite(lua_State *L) { - int colornum = ((int)luaL_checkinteger(L, 1)) & MAXSKINCOLORS; + int colornum = ((int)luaL_checkinteger(L, 1)) % MAXSKINCOLORS; lua_pushinteger(L, Color_Opposite[colornum*2]); // push color lua_pushinteger(L, Color_Opposite[colornum*2+1]); // push frame return 2; From f559b50995ea7be5e7b3119a095aeab8cc235773 Mon Sep 17 00:00:00 2001 From: Inuyasha Date: Wed, 20 Jan 2016 09:25:28 -0800 Subject: [PATCH 12/20] fix bad lstring usage in map header lua This is not how you use pushlstring! This is actually sending uninitialized memory to Lua, which is making scripts have inconsistent results (duh?) c/o JTE: "Tell Red they're a doofus." --- src/lua_maplib.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 0a12478c..85c3b094 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1162,9 +1162,9 @@ static int mapheaderinfo_get(lua_State *L) //for (i = 0; i < 21; i++) // if (!header->lvlttl[i]) // break; - lua_pushlstring(L, header->lvlttl, 21); + lua_pushstring(L, header->lvlttl); } else if (fastcmp(field,"subttl")) - lua_pushlstring(L, header->subttl, 32); + lua_pushstring(L, header->subttl); else if (fastcmp(field,"actnum")) lua_pushinteger(L, header->actnum); else if (fastcmp(field,"typeoflevel")) @@ -1176,7 +1176,7 @@ static int mapheaderinfo_get(lua_State *L) else if (fastcmp(field,"musicslottrack")) lua_pushinteger(L, header->musicslottrack); else if (fastcmp(field,"forcecharacter")) - lua_pushlstring(L, header->forcecharacter, 16); + lua_pushstring(L, header->forcecharacter); else if (fastcmp(field,"weather")) lua_pushinteger(L, header->weather); else if (fastcmp(field,"skynum")) @@ -1188,11 +1188,11 @@ static int mapheaderinfo_get(lua_State *L) else if (fastcmp(field,"skybox_scalez")) lua_pushinteger(L, header->skybox_scalez); else if (fastcmp(field,"interscreen")) - lua_pushlstring(L, header->interscreen, 8); + lua_pushstring(L, header->interscreen); else if (fastcmp(field,"runsoc")) - lua_pushlstring(L, header->runsoc, 32); + lua_pushstring(L, header->runsoc); else if (fastcmp(field,"scriptname")) - lua_pushlstring(L, header->scriptname, 32); + lua_pushstring(L, header->scriptname); else if (fastcmp(field,"precutscenenum")) lua_pushinteger(L, header->precutscenenum); else if (fastcmp(field,"cutscenenum")) @@ -1221,7 +1221,7 @@ static int mapheaderinfo_get(lua_State *L) for (;i < header->numCustomOptions && !fastcmp(field, header->customopts[i].option); ++i); if(i < header->numCustomOptions) - lua_pushlstring(L, header->customopts[i].value, 255); + lua_pushstring(L, header->customopts[i].value); else lua_pushnil(L); } From c30188f9fdfa6cf674e998b962d99e3f203a2606 Mon Sep 17 00:00:00 2001 From: Inuyasha Date: Wed, 20 Jan 2016 09:42:35 -0800 Subject: [PATCH 13/20] interscreen is a lump name and thus needs lstring ... not just lstring though, but the behavior with i that is used elsewhere. --- src/lua_maplib.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 85c3b094..6f28997a 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1157,13 +1157,10 @@ static int mapheaderinfo_get(lua_State *L) { mapheader_t *header = *((mapheader_t **)luaL_checkudata(L, 1, META_MAPHEADER)); const char *field = luaL_checkstring(L, 2); - //INT16 i; - if (fastcmp(field,"lvlttl")) { - //for (i = 0; i < 21; i++) - // if (!header->lvlttl[i]) - // break; + INT16 i; + if (fastcmp(field,"lvlttl")) lua_pushstring(L, header->lvlttl); - } else if (fastcmp(field,"subttl")) + else if (fastcmp(field,"subttl")) lua_pushstring(L, header->subttl); else if (fastcmp(field,"actnum")) lua_pushinteger(L, header->actnum); @@ -1187,9 +1184,12 @@ static int mapheaderinfo_get(lua_State *L) lua_pushinteger(L, header->skybox_scaley); else if (fastcmp(field,"skybox_scalez")) lua_pushinteger(L, header->skybox_scalez); - else if (fastcmp(field,"interscreen")) - lua_pushstring(L, header->interscreen); - else if (fastcmp(field,"runsoc")) + else if (fastcmp(field,"interscreen")) { + for (i = 0; i < 8; i++) + if (!header->interscreen[i]) + break; + lua_pushlstring(L, header->interscreen, i); + } else if (fastcmp(field,"runsoc")) lua_pushstring(L, header->runsoc); else if (fastcmp(field,"scriptname")) lua_pushstring(L, header->scriptname); From c7e540a870f53711a3580b3510de83e33d8e14bc Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 21 Jan 2016 13:50:05 -0500 Subject: [PATCH 14/20] whitespace cleanup --- src/r_bsp.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/r_bsp.c b/src/r_bsp.c index badf8bda..c547713b 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -935,14 +935,14 @@ static void R_Subsector(size_t num) ffloor[numffloors].plane = NULL; ffloor[numffloors].polyobj = NULL; - - floorcenterz = + + floorcenterz = #ifdef ESLOPE frontsector->f_slope ? P_GetZAt(frontsector->f_slope, frontsector->soundorg.x, frontsector->soundorg.y) : #endif frontsector->floorheight; - - ceilingcenterz = + + ceilingcenterz = #ifdef ESLOPE frontsector->c_slope ? P_GetZAt(frontsector->c_slope, frontsector->soundorg.x, frontsector->soundorg.y) : #endif @@ -953,8 +953,8 @@ static void R_Subsector(size_t num) *rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : #endif *rover->bottomheight; - - planecenterz = + + planecenterz = #ifdef ESLOPE *rover->b_slope ? P_GetZAt(*rover->b_slope, frontsector->soundorg.x, frontsector->soundorg.y) : #endif @@ -966,7 +966,7 @@ static void R_Subsector(size_t num) { light = R_GetPlaneLight(frontsector, planecenterz, viewz < *rover->bottomheight); - + ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic, *frontsector->lightlist[light].lightlevel, *rover->bottomxoffs, *rover->bottomyoffs, *rover->bottomangle, frontsector->lightlist[light].extra_colormap, rover @@ -1002,8 +1002,8 @@ static void R_Subsector(size_t num) *rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : #endif *rover->topheight; - - planecenterz = + + planecenterz = #ifdef ESLOPE *rover->t_slope ? P_GetZAt(*rover->t_slope, frontsector->soundorg.x, frontsector->soundorg.y) : #endif @@ -1014,7 +1014,7 @@ static void R_Subsector(size_t num) || (viewz < heightcheck && (rover->flags & FF_BOTHPLANES)))) { light = R_GetPlaneLight(frontsector, planecenterz, viewz < *rover->topheight); - + ffloor[numffloors].plane = R_FindPlane(*rover->topheight, *rover->toppic, *frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *rover->topangle, frontsector->lightlist[light].extra_colormap, rover From f65c5c016adb2456b020d3a8b280cc963370aeca Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 21 Jan 2016 20:27:35 +0000 Subject: [PATCH 15/20] Fix shadowing in mapheaderinfo_get --- src/lua_maplib.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 6f28997a..38920c22 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1217,11 +1217,11 @@ static int mapheaderinfo_get(lua_State *L) else { // Read custom vars now // (note: don't include the "LUA." in your lua scripts!) - UINT8 i = 0; - for (;i < header->numCustomOptions && !fastcmp(field, header->customopts[i].option); ++i); + UINT8 j = 0; + for (;j < header->numCustomOptions && !fastcmp(field, header->customopts[j].option); ++j); - if(i < header->numCustomOptions) - lua_pushstring(L, header->customopts[i].value); + if(j < header->numCustomOptions) + lua_pushstring(L, header->customopts[j].value); else lua_pushnil(L); } From 63a3e03bb0ed8e57860892acc4c8444e8be06d54 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 23 Jan 2016 18:59:17 +0000 Subject: [PATCH 16/20] Fixed math for calculating current texture in texture animations --- src/p_spec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index cac822ac..81994d46 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4671,11 +4671,11 @@ void P_UpdateSpecials(void) // ANIMATE TEXTURES for (anim = anims; anim < lastanim; anim++) { - for (i = anim->basepic; i < anim->basepic + anim->numpics; i++) + for (i = 0; i < anim->numpics; i++) { pic = anim->basepic + ((leveltime/anim->speed + i) % anim->numpics); if (anim->istexture) - texturetranslation[i] = pic; + texturetranslation[anim->basepic+i] = pic; } } From 14dcd2404b1f5972cee0b6dc4c559f2506c00a02 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 25 Jan 2016 16:45:08 +0000 Subject: [PATCH 17/20] Fixed compiler warnings to the best of my ability Hopefully this all still works properly, try not to kill me if it doesn't =V --- src/blua/liolib.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index 2d20f529..e9a50f37 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -167,8 +167,12 @@ static int StartsWith(const char *a, const char *b) // this is wolfs being lazy static int io_open (lua_State *L) { const char *filename = luaL_checkstring(L, 1); - int pass = 0; int i; + int pass = 0; size_t i; int length = strlen(filename) - 1; + char *splitter, *splitter2; + char *destFilename = NULL; + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf; for (i = 0; i < (sizeof (whitelist) / sizeof(const char *)); i++) { if (!stricmp(&filename[length - (strlen(whitelist[i]) - 1)], whitelist[i])) @@ -184,26 +188,27 @@ static int io_open (lua_State *L) { return pushresult(L,0,filename); } I_mkdir("luafiles", 0755); - char *splitter = filename; + + strcpy(destFilename, filename); // copy file name to temp string + splitter = destFilename; while ((splitter = strchr(splitter, '/'))) { *splitter = 0; - I_mkdir(va("luafiles"PATHSEP"%s", filename), 0755); + I_mkdir(va("luafiles"PATHSEP"%s", destFilename), 0755); *splitter = '/'; splitter++; } - char *splitter2 = filename; + splitter2 = destFilename; while ((splitter2 = strchr(splitter2, '\\'))) { *splitter2 = 0; - I_mkdir(va("luafiles"PATHSEP"%s", filename), 0755); + I_mkdir(va("luafiles"PATHSEP"%s", destFilename), 0755); *splitter2 = '\\'; splitter2++; } - char* destFilename = va("luafiles"PATHSEP"%s", filename); + destFilename = va("luafiles"PATHSEP"%s", destFilename); filename = destFilename; - const char *mode = luaL_optstring(L, 2, "r"); - FILE **pf = newfile(L); + pf = newfile(L); *pf = fopen(filename, mode); return (*pf == NULL) ? pushresult(L, 0, filename) : 1; } From 9c299e5ad484a153d16e127881f4f7701295328e Mon Sep 17 00:00:00 2001 From: Nipples the Enchilada Date: Mon, 25 Jan 2016 22:48:45 -0500 Subject: [PATCH 18/20] Fix and clean up io_open after MI broke it horribly strcpy(NULL, filename); congrats --- src/blua/liolib.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index e9a50f37..dee512bf 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -166,16 +166,18 @@ static int StartsWith(const char *a, const char *b) // this is wolfs being lazy static int io_open (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - int pass = 0; size_t i; - int length = strlen(filename) - 1; - char *splitter, *splitter2; - char *destFilename = NULL; - const char *mode = luaL_optstring(L, 2, "r"); FILE **pf; + const char *filename = luaL_checkstring(L, 1); + int pass = 0; + size_t i; + int length = strlen(filename); + char *splitter, *forward, *backward; + char *destFilename; + const char *mode = luaL_optstring(L, 2, "r"); + for (i = 0; i < (sizeof (whitelist) / sizeof(const char *)); i++) { - if (!stricmp(&filename[length - (strlen(whitelist[i]) - 1)], whitelist[i])) + if (!stricmp(&filename[length - strlen(whitelist[i])], whitelist[i])) { pass = 1; break; @@ -187,29 +189,27 @@ static int io_open (lua_State *L) { luaL_error(L,"access denied to %s", filename); return pushresult(L,0,filename); } - I_mkdir("luafiles", 0755); - - strcpy(destFilename, filename); // copy file name to temp string + + destFilename = va("luafiles"PATHSEP"%s", filename); + + // Make directories as needed splitter = destFilename; - while ((splitter = strchr(splitter, '/'))) + + forward = strchr(splitter, '/'); + backward = strchr(splitter, '\\'); + while ((splitter = (forward && backward) ? min(forward, backward) : (forward ?: backward))) { *splitter = 0; - I_mkdir(va("luafiles"PATHSEP"%s", destFilename), 0755); + I_mkdir(destFilename, 0755); *splitter = '/'; splitter++; + + forward = strchr(splitter, '/'); + backward = strchr(splitter, '\\'); } - splitter2 = destFilename; - while ((splitter2 = strchr(splitter2, '\\'))) - { - *splitter2 = 0; - I_mkdir(va("luafiles"PATHSEP"%s", destFilename), 0755); - *splitter2 = '\\'; - splitter2++; - } - destFilename = va("luafiles"PATHSEP"%s", destFilename); - filename = destFilename; + pf = newfile(L); - *pf = fopen(filename, mode); + *pf = fopen(destFilename, mode); return (*pf == NULL) ? pushresult(L, 0, filename) : 1; } From 2eedecb93ac87e91277c076e39b4c3358e7c42eb Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 26 Jan 2016 12:07:28 +0000 Subject: [PATCH 19/20] Get rid of unneeded tab spaces Least I can do to make up for breaking io.open in the first place :E --- src/blua/liolib.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index dee512bf..27ff7449 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -174,7 +174,7 @@ static int io_open (lua_State *L) { char *splitter, *forward, *backward; char *destFilename; const char *mode = luaL_optstring(L, 2, "r"); - + for (i = 0; i < (sizeof (whitelist) / sizeof(const char *)); i++) { if (!stricmp(&filename[length - strlen(whitelist[i])], whitelist[i])) @@ -189,12 +189,12 @@ static int io_open (lua_State *L) { luaL_error(L,"access denied to %s", filename); return pushresult(L,0,filename); } - + destFilename = va("luafiles"PATHSEP"%s", filename); - + // Make directories as needed splitter = destFilename; - + forward = strchr(splitter, '/'); backward = strchr(splitter, '\\'); while ((splitter = (forward && backward) ? min(forward, backward) : (forward ?: backward))) @@ -203,11 +203,11 @@ static int io_open (lua_State *L) { I_mkdir(destFilename, 0755); *splitter = '/'; splitter++; - + forward = strchr(splitter, '/'); backward = strchr(splitter, '\\'); } - + pf = newfile(L); *pf = fopen(destFilename, mode); return (*pf == NULL) ? pushresult(L, 0, filename) : 1; From db7da456d2d330f3c116e69017a61f3c82012614 Mon Sep 17 00:00:00 2001 From: wolfy852 Date: Fri, 29 Jan 2016 01:38:41 -0600 Subject: [PATCH 20/20] Remove block on % in filename strings According to Alam, supporting this shouldn't cause any issues. --- src/blua/liolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index 27ff7449..a9e71f74 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -184,7 +184,7 @@ static int io_open (lua_State *L) { } } if (strstr(filename, "..") || strchr(filename, ':') || StartsWith(filename, "\\") - || StartsWith(filename, "/") || strchr(filename, '%') || !pass) + || StartsWith(filename, "/") || !pass) { luaL_error(L,"access denied to %s", filename); return pushresult(L,0,filename);