diff options
Diffstat (limited to 'loslib.c')
-rw-r--r-- | loslib.c | 60 |
1 files changed, 37 insertions, 23 deletions
@@ -1,5 +1,5 @@ | |||
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 | ** Standard Operating System library | 3 | ** Standard Operating System library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -54,7 +54,12 @@ | |||
54 | */ | 54 | */ |
55 | #define l_timet lua_Integer | 55 | #define l_timet lua_Integer |
56 | #define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t)) | 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 | #endif /* } */ | 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) { | 206 | /* maximum value for date fields (to avoid arithmetic overflows with 'int') */ |
202 | int res, isnum; | 207 | #if !defined(L_MAXDATEFIELD) |
203 | lua_getfield(L, -1, key); | 208 | #define L_MAXDATEFIELD (INT_MAX / 2) |
204 | res = (int)lua_tointegerx(L, -1, &isnum); | 209 | #endif |
205 | if (!isnum) { | 210 | |
206 | if (d < 0) | 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 | return luaL_error(L, "field '%s' missing in date table", key); | 219 | return luaL_error(L, "field '%s' missing in date table", key); |
208 | res = d; | 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 | lua_pop(L, 1); | 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 | else | 264 | else |
248 | stm = l_localtime(&t, &tmr); | 265 | stm = l_localtime(&t, &tmr); |
249 | if (stm == NULL) /* invalid date? */ | 266 | if (stm == NULL) /* invalid date? */ |
250 | lua_pushnil(L); | 267 | luaL_error(L, "time result cannot be represented in this installation"); |
251 | else if (strcmp(s, "*t") == 0) { | 268 | if (strcmp(s, "*t") == 0) { |
252 | lua_createtable(L, 0, 9); /* 9 = number of fields */ | 269 | lua_createtable(L, 0, 9); /* 9 = number of fields */ |
253 | setfield(L, "sec", stm->tm_sec); | 270 | setfield(L, "sec", stm->tm_sec); |
254 | setfield(L, "min", stm->tm_min); | 271 | setfield(L, "min", stm->tm_min); |
@@ -290,21 +307,18 @@ static int os_time (lua_State *L) { | |||
290 | struct tm ts; | 307 | struct tm ts; |
291 | luaL_checktype(L, 1, LUA_TTABLE); | 308 | luaL_checktype(L, 1, LUA_TTABLE); |
292 | lua_settop(L, 1); /* make sure table is at the top */ | 309 | lua_settop(L, 1); /* make sure table is at the top */ |
293 | ts.tm_sec = getfield(L, "sec", 0); | 310 | ts.tm_sec = getfield(L, "sec", 0, 0); |
294 | ts.tm_min = getfield(L, "min", 0); | 311 | ts.tm_min = getfield(L, "min", 0, 0); |
295 | ts.tm_hour = getfield(L, "hour", 12); | 312 | ts.tm_hour = getfield(L, "hour", 12, 0); |
296 | ts.tm_mday = getfield(L, "day", -1); | 313 | ts.tm_mday = getfield(L, "day", -1, 0); |
297 | ts.tm_mon = getfield(L, "month", -1) - 1; | 314 | ts.tm_mon = getfield(L, "month", -1, 1); |
298 | ts.tm_year = getfield(L, "year", -1) - 1900; | 315 | ts.tm_year = getfield(L, "year", -1, 1900); |
299 | ts.tm_isdst = getboolfield(L, "isdst"); | 316 | ts.tm_isdst = getboolfield(L, "isdst"); |
300 | t = mktime(&ts); | 317 | t = mktime(&ts); |
301 | } | 318 | } |
302 | if (t != (time_t)(l_timet)t) | 319 | if (t != (time_t)(l_timet)t || t == (time_t)(-1)) |
303 | luaL_error(L, "time result cannot be represented in this Lua installation"); | 320 | luaL_error(L, "time result cannot be represented in this installation"); |
304 | else if (t == (time_t)(-1)) | 321 | l_pushtime(L, t); |
305 | lua_pushnil(L); | ||
306 | else | ||
307 | l_pushtime(L, t); | ||
308 | return 1; | 322 | return 1; |
309 | } | 323 | } |
310 | 324 | ||