Skip to content

Commit 4af03c5

Browse files
committed
better treatment for integer overflows + all errors throw an error
(instead of returning nil)
1 parent bde17a4 commit 4af03c5

1 file changed

Lines changed: 37 additions & 23 deletions

File tree

loslib.c

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** $Id: loslib.c,v 1.56 2015/02/09 17:41:54 roberto Exp roberto $
2+
** $Id: loslib.c,v 1.57 2015/04/10 17:41:04 roberto Exp roberto $
33
** Standard Operating System library
44
** See Copyright Notice in lua.h
55
*/
@@ -54,7 +54,12 @@
5454
*/
5555
#define l_timet lua_Integer
5656
#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t))
57-
#define l_checktime(L,a) ((time_t)luaL_checkinteger(L,a))
57+
58+
static time_t l_checktime (lua_State *L, int arg) {
59+
lua_Integer t = luaL_checkinteger(L, arg);
60+
luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds");
61+
return (time_t)t;
62+
}
5863

5964
#endif /* } */
6065

@@ -198,17 +203,29 @@ static int getboolfield (lua_State *L, const char *key) {
198203
}
199204

200205

201-
static int getfield (lua_State *L, const char *key, int d) {
202-
int res, isnum;
203-
lua_getfield(L, -1, key);
204-
res = (int)lua_tointegerx(L, -1, &isnum);
205-
if (!isnum) {
206-
if (d < 0)
206+
/* maximum value for date fields (to avoid arithmetic overflows with 'int') */
207+
#if !defined(L_MAXDATEFIELD)
208+
#define L_MAXDATEFIELD (INT_MAX / 2)
209+
#endif
210+
211+
static int getfield (lua_State *L, const char *key, int d, int delta) {
212+
int isnum;
213+
int t = lua_getfield(L, -1, key);
214+
lua_Integer res = lua_tointegerx(L, -1, &isnum);
215+
if (!isnum) { /* field is not a number? */
216+
if (t != LUA_TNIL) /* some other value? */
217+
return luaL_error(L, "field '%s' not an integer", key);
218+
else if (d < 0) /* abssent field; no default? */
207219
return luaL_error(L, "field '%s' missing in date table", key);
208220
res = d;
209221
}
222+
else {
223+
if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD))
224+
return luaL_error(L, "field '%s' out-of-bounds", key);
225+
res -= delta;
226+
}
210227
lua_pop(L, 1);
211-
return res;
228+
return (int)res;
212229
}
213230

214231

@@ -247,8 +264,8 @@ static int os_date (lua_State *L) {
247264
else
248265
stm = l_localtime(&t, &tmr);
249266
if (stm == NULL) /* invalid date? */
250-
lua_pushnil(L);
251-
else if (strcmp(s, "*t") == 0) {
267+
luaL_error(L, "time result cannot be represented in this installation");
268+
if (strcmp(s, "*t") == 0) {
252269
lua_createtable(L, 0, 9); /* 9 = number of fields */
253270
setfield(L, "sec", stm->tm_sec);
254271
setfield(L, "min", stm->tm_min);
@@ -290,21 +307,18 @@ static int os_time (lua_State *L) {
290307
struct tm ts;
291308
luaL_checktype(L, 1, LUA_TTABLE);
292309
lua_settop(L, 1); /* make sure table is at the top */
293-
ts.tm_sec = getfield(L, "sec", 0);
294-
ts.tm_min = getfield(L, "min", 0);
295-
ts.tm_hour = getfield(L, "hour", 12);
296-
ts.tm_mday = getfield(L, "day", -1);
297-
ts.tm_mon = getfield(L, "month", -1) - 1;
298-
ts.tm_year = getfield(L, "year", -1) - 1900;
310+
ts.tm_sec = getfield(L, "sec", 0, 0);
311+
ts.tm_min = getfield(L, "min", 0, 0);
312+
ts.tm_hour = getfield(L, "hour", 12, 0);
313+
ts.tm_mday = getfield(L, "day", -1, 0);
314+
ts.tm_mon = getfield(L, "month", -1, 1);
315+
ts.tm_year = getfield(L, "year", -1, 1900);
299316
ts.tm_isdst = getboolfield(L, "isdst");
300317
t = mktime(&ts);
301318
}
302-
if (t != (time_t)(l_timet)t)
303-
luaL_error(L, "time result cannot be represented in this Lua installation");
304-
else if (t == (time_t)(-1))
305-
lua_pushnil(L);
306-
else
307-
l_pushtime(L, t);
319+
if (t != (time_t)(l_timet)t || t == (time_t)(-1))
320+
luaL_error(L, "time result cannot be represented in this installation");
321+
l_pushtime(L, t);
308322
return 1;
309323
}
310324

0 commit comments

Comments
 (0)