|
1 | 1 | /* |
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 $ |
3 | 3 | ** Standard Operating System library |
4 | 4 | ** See Copyright Notice in lua.h |
5 | 5 | */ |
|
54 | 54 | */ |
55 | 55 | #define l_timet lua_Integer |
56 | 56 | #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 | +} |
58 | 63 |
|
59 | 64 | #endif /* } */ |
60 | 65 |
|
@@ -198,17 +203,29 @@ static int getboolfield (lua_State *L, const char *key) { |
198 | 203 | } |
199 | 204 |
|
200 | 205 |
|
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? */ |
207 | 219 | return luaL_error(L, "field '%s' missing in date table", key); |
208 | 220 | res = d; |
209 | 221 | } |
| 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 | + } |
210 | 227 | lua_pop(L, 1); |
211 | | - return res; |
| 228 | + return (int)res; |
212 | 229 | } |
213 | 230 |
|
214 | 231 |
|
@@ -247,8 +264,8 @@ static int os_date (lua_State *L) { |
247 | 264 | else |
248 | 265 | stm = l_localtime(&t, &tmr); |
249 | 266 | 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) { |
252 | 269 | lua_createtable(L, 0, 9); /* 9 = number of fields */ |
253 | 270 | setfield(L, "sec", stm->tm_sec); |
254 | 271 | setfield(L, "min", stm->tm_min); |
@@ -290,21 +307,18 @@ static int os_time (lua_State *L) { |
290 | 307 | struct tm ts; |
291 | 308 | luaL_checktype(L, 1, LUA_TTABLE); |
292 | 309 | 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); |
299 | 316 | ts.tm_isdst = getboolfield(L, "isdst"); |
300 | 317 | t = mktime(&ts); |
301 | 318 | } |
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); |
308 | 322 | return 1; |
309 | 323 | } |
310 | 324 |
|
|
0 commit comments