better treatment for integer overflows + all errors throw an error
(instead of returning nil)
This commit is contained in:
60
loslib.c
60
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
|
** Standard Operating System library
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -54,7 +54,12 @@
|
|||||||
*/
|
*/
|
||||||
#define l_timet lua_Integer
|
#define l_timet lua_Integer
|
||||||
#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t))
|
#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 /* } */
|
#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) {
|
/* maximum value for date fields (to avoid arithmetic overflows with 'int') */
|
||||||
int res, isnum;
|
#if !defined(L_MAXDATEFIELD)
|
||||||
lua_getfield(L, -1, key);
|
#define L_MAXDATEFIELD (INT_MAX / 2)
|
||||||
res = (int)lua_tointegerx(L, -1, &isnum);
|
#endif
|
||||||
if (!isnum) {
|
|
||||||
if (d < 0)
|
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);
|
return luaL_error(L, "field '%s' missing in date table", key);
|
||||||
res = d;
|
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);
|
lua_pop(L, 1);
|
||||||
return res;
|
return (int)res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -247,8 +264,8 @@ static int os_date (lua_State *L) {
|
|||||||
else
|
else
|
||||||
stm = l_localtime(&t, &tmr);
|
stm = l_localtime(&t, &tmr);
|
||||||
if (stm == NULL) /* invalid date? */
|
if (stm == NULL) /* invalid date? */
|
||||||
lua_pushnil(L);
|
luaL_error(L, "time result cannot be represented in this installation");
|
||||||
else if (strcmp(s, "*t") == 0) {
|
if (strcmp(s, "*t") == 0) {
|
||||||
lua_createtable(L, 0, 9); /* 9 = number of fields */
|
lua_createtable(L, 0, 9); /* 9 = number of fields */
|
||||||
setfield(L, "sec", stm->tm_sec);
|
setfield(L, "sec", stm->tm_sec);
|
||||||
setfield(L, "min", stm->tm_min);
|
setfield(L, "min", stm->tm_min);
|
||||||
@@ -290,21 +307,18 @@ static int os_time (lua_State *L) {
|
|||||||
struct tm ts;
|
struct tm ts;
|
||||||
luaL_checktype(L, 1, LUA_TTABLE);
|
luaL_checktype(L, 1, LUA_TTABLE);
|
||||||
lua_settop(L, 1); /* make sure table is at the top */
|
lua_settop(L, 1); /* make sure table is at the top */
|
||||||
ts.tm_sec = getfield(L, "sec", 0);
|
ts.tm_sec = getfield(L, "sec", 0, 0);
|
||||||
ts.tm_min = getfield(L, "min", 0);
|
ts.tm_min = getfield(L, "min", 0, 0);
|
||||||
ts.tm_hour = getfield(L, "hour", 12);
|
ts.tm_hour = getfield(L, "hour", 12, 0);
|
||||||
ts.tm_mday = getfield(L, "day", -1);
|
ts.tm_mday = getfield(L, "day", -1, 0);
|
||||||
ts.tm_mon = getfield(L, "month", -1) - 1;
|
ts.tm_mon = getfield(L, "month", -1, 1);
|
||||||
ts.tm_year = getfield(L, "year", -1) - 1900;
|
ts.tm_year = getfield(L, "year", -1, 1900);
|
||||||
ts.tm_isdst = getboolfield(L, "isdst");
|
ts.tm_isdst = getboolfield(L, "isdst");
|
||||||
t = mktime(&ts);
|
t = mktime(&ts);
|
||||||
}
|
}
|
||||||
if (t != (time_t)(l_timet)t)
|
if (t != (time_t)(l_timet)t || t == (time_t)(-1))
|
||||||
luaL_error(L, "time result cannot be represented in this Lua installation");
|
luaL_error(L, "time result cannot be represented in this installation");
|
||||||
else if (t == (time_t)(-1))
|
l_pushtime(L, t);
|
||||||
lua_pushnil(L);
|
|
||||||
else
|
|
||||||
l_pushtime(L, t);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user