From 4af03c5ae10cfae115069dc5de8ec13b771df749 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Sat, 4 Jul 2015 13:35:14 -0300 Subject: better treatment for integer overflows + all errors throw an error (instead of returning nil) --- loslib.c | 60 +++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 23 deletions(-) (limited to 'loslib.c') diff --git a/loslib.c b/loslib.c index bf436b81..eb444bb2 100644 --- a/loslib.c +++ b/loslib.c @@ -1,5 +1,5 @@ /* -** $Id: loslib.c,v 1.56 2015/02/09 17:41:54 roberto Exp roberto $ +** $Id: loslib.c,v 1.57 2015/04/10 17:41:04 roberto Exp roberto $ ** Standard Operating System library ** See Copyright Notice in lua.h */ @@ -54,7 +54,12 @@ */ #define l_timet lua_Integer #define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t)) -#define l_checktime(L,a) ((time_t)luaL_checkinteger(L,a)) + +static time_t l_checktime (lua_State *L, int arg) { + lua_Integer t = luaL_checkinteger(L, arg); + luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds"); + return (time_t)t; +} #endif /* } */ @@ -198,17 +203,29 @@ static int getboolfield (lua_State *L, const char *key) { } -static int getfield (lua_State *L, const char *key, int d) { - int res, isnum; - lua_getfield(L, -1, key); - res = (int)lua_tointegerx(L, -1, &isnum); - if (!isnum) { - if (d < 0) +/* maximum value for date fields (to avoid arithmetic overflows with 'int') */ +#if !defined(L_MAXDATEFIELD) +#define L_MAXDATEFIELD (INT_MAX / 2) +#endif + +static int getfield (lua_State *L, const char *key, int d, int delta) { + int isnum; + int t = lua_getfield(L, -1, key); + lua_Integer res = lua_tointegerx(L, -1, &isnum); + if (!isnum) { /* field is not a number? */ + if (t != LUA_TNIL) /* some other value? */ + return luaL_error(L, "field '%s' not an integer", key); + else if (d < 0) /* abssent field; no default? */ return luaL_error(L, "field '%s' missing in date table", key); res = d; } + else { + if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD)) + return luaL_error(L, "field '%s' out-of-bounds", key); + res -= delta; + } lua_pop(L, 1); - return res; + return (int)res; } @@ -247,8 +264,8 @@ static int os_date (lua_State *L) { else stm = l_localtime(&t, &tmr); if (stm == NULL) /* invalid date? */ - lua_pushnil(L); - else if (strcmp(s, "*t") == 0) { + luaL_error(L, "time result cannot be represented in this installation"); + if (strcmp(s, "*t") == 0) { lua_createtable(L, 0, 9); /* 9 = number of fields */ setfield(L, "sec", stm->tm_sec); setfield(L, "min", stm->tm_min); @@ -290,21 +307,18 @@ static int os_time (lua_State *L) { struct tm ts; luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 1); /* make sure table is at the top */ - ts.tm_sec = getfield(L, "sec", 0); - ts.tm_min = getfield(L, "min", 0); - ts.tm_hour = getfield(L, "hour", 12); - ts.tm_mday = getfield(L, "day", -1); - ts.tm_mon = getfield(L, "month", -1) - 1; - ts.tm_year = getfield(L, "year", -1) - 1900; + ts.tm_sec = getfield(L, "sec", 0, 0); + ts.tm_min = getfield(L, "min", 0, 0); + ts.tm_hour = getfield(L, "hour", 12, 0); + ts.tm_mday = getfield(L, "day", -1, 0); + ts.tm_mon = getfield(L, "month", -1, 1); + ts.tm_year = getfield(L, "year", -1, 1900); ts.tm_isdst = getboolfield(L, "isdst"); t = mktime(&ts); } - if (t != (time_t)(l_timet)t) - luaL_error(L, "time result cannot be represented in this Lua installation"); - else if (t == (time_t)(-1)) - lua_pushnil(L); - else - l_pushtime(L, t); + if (t != (time_t)(l_timet)t || t == (time_t)(-1)) + luaL_error(L, "time result cannot be represented in this installation"); + l_pushtime(L, t); return 1; } -- cgit v1.2.3-55-g6feb