aboutsummaryrefslogtreecommitdiff
path: root/loslib.c
diff options
context:
space:
mode:
Diffstat (limited to 'loslib.c')
-rw-r--r--loslib.c76
1 files changed, 48 insertions, 28 deletions
diff --git a/loslib.c b/loslib.c
index 8809e5ea..7812d29b 100644
--- a/loslib.c
+++ b/loslib.c
@@ -58,18 +58,20 @@
58** =================================================================== 58** ===================================================================
59*/ 59*/
60 60
61#if !defined(l_time_t) /* { */
62/* 61/*
63** type to represent time_t in Lua 62** type to represent time_t in Lua
64*/ 63*/
64#if !defined(LUA_NUMTIME) /* { */
65
65#define l_timet lua_Integer 66#define l_timet lua_Integer
66#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t)) 67#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t))
68#define l_gettime(L,arg) luaL_checkinteger(L, arg)
67 69
68static time_t l_checktime (lua_State *L, int arg) { 70#else /* }{ */
69 lua_Integer t = luaL_checkinteger(L, arg); 71
70 luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds"); 72#define l_timet lua_Number
71 return (time_t)t; 73#define l_pushtime(L,t) lua_pushnumber(L,(lua_Number)(t))
72} 74#define l_gettime(L,arg) luaL_checknumber(L, arg)
73 75
74#endif /* } */ 76#endif /* } */
75 77
@@ -193,11 +195,25 @@ static int os_clock (lua_State *L) {
193** ======================================================= 195** =======================================================
194*/ 196*/
195 197
196static void setfield (lua_State *L, const char *key, int value) { 198/*
197 lua_pushinteger(L, value); 199** About the overflow check: an overflow cannot occurr when time
200** is represented by a lua_Integer, because either lua_Integer is
201** large enough to represent all int fields or it is not large enough
202** to represent a time that cause a field to overflow. However, if
203** times are represented as doubles and lua_Integer is int, then the
204** time 0x1.e1853b0d184f6p+55 would cause an overflow when adding 1900
205** to compute the year.
206*/
207static void setfield (lua_State *L, const char *key, int value, int delta) {
208 #if (defined(LUA_NUMTIME) && LUA_MAXINTEGER <= INT_MAX)
209 if (value > LUA_MAXINTEGER - delta)
210 luaL_error(L, "field '%s' is out-of-bound", key);
211 #endif
212 lua_pushinteger(L, (lua_Integer)value + delta);
198 lua_setfield(L, -2, key); 213 lua_setfield(L, -2, key);
199} 214}
200 215
216
201static void setboolfield (lua_State *L, const char *key, int value) { 217static void setboolfield (lua_State *L, const char *key, int value) {
202 if (value < 0) /* undefined? */ 218 if (value < 0) /* undefined? */
203 return; /* does not set field */ 219 return; /* does not set field */
@@ -210,14 +226,14 @@ static void setboolfield (lua_State *L, const char *key, int value) {
210** Set all fields from structure 'tm' in the table on top of the stack 226** Set all fields from structure 'tm' in the table on top of the stack
211*/ 227*/
212static void setallfields (lua_State *L, struct tm *stm) { 228static void setallfields (lua_State *L, struct tm *stm) {
213 setfield(L, "sec", stm->tm_sec); 229 setfield(L, "year", stm->tm_year, 1900);
214 setfield(L, "min", stm->tm_min); 230 setfield(L, "month", stm->tm_mon, 1);
215 setfield(L, "hour", stm->tm_hour); 231 setfield(L, "day", stm->tm_mday, 0);
216 setfield(L, "day", stm->tm_mday); 232 setfield(L, "hour", stm->tm_hour, 0);
217 setfield(L, "month", stm->tm_mon + 1); 233 setfield(L, "min", stm->tm_min, 0);
218 setfield(L, "year", stm->tm_year + 1900); 234 setfield(L, "sec", stm->tm_sec, 0);
219 setfield(L, "wday", stm->tm_wday + 1); 235 setfield(L, "yday", stm->tm_yday, 1);
220 setfield(L, "yday", stm->tm_yday + 1); 236 setfield(L, "wday", stm->tm_wday, 1);
221 setboolfield(L, "isdst", stm->tm_isdst); 237 setboolfield(L, "isdst", stm->tm_isdst);
222} 238}
223 239
@@ -230,11 +246,6 @@ static int getboolfield (lua_State *L, const char *key) {
230} 246}
231 247
232 248
233/* maximum value for date fields (to avoid arithmetic overflows with 'int') */
234#if !defined(L_MAXDATEFIELD)
235#define L_MAXDATEFIELD (INT_MAX / 2)
236#endif
237
238static int getfield (lua_State *L, const char *key, int d, int delta) { 249static int getfield (lua_State *L, const char *key, int d, int delta) {
239 int isnum; 250 int isnum;
240 int t = lua_getfield(L, -1, key); /* get field and its type */ 251 int t = lua_getfield(L, -1, key); /* get field and its type */
@@ -247,7 +258,9 @@ static int getfield (lua_State *L, const char *key, int d, int delta) {
247 res = d; 258 res = d;
248 } 259 }
249 else { 260 else {
250 if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD)) 261 /* unsigned avoids overflow when lua_Integer has 32 bits */
262 if (!(res >= 0 ? (lua_Unsigned)res <= (lua_Unsigned)INT_MAX + delta
263 : (lua_Integer)INT_MIN + delta <= res))
251 return luaL_error(L, "field '%s' is out-of-bound", key); 264 return luaL_error(L, "field '%s' is out-of-bound", key);
252 res -= delta; 265 res -= delta;
253 } 266 }
@@ -275,6 +288,13 @@ static const char *checkoption (lua_State *L, const char *conv,
275} 288}
276 289
277 290
291static time_t l_checktime (lua_State *L, int arg) {
292 l_timet t = l_gettime(L, arg);
293 luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds");
294 return (time_t)t;
295}
296
297
278/* maximum size for an individual 'strftime' item */ 298/* maximum size for an individual 'strftime' item */
279#define SIZETIMEFMT 250 299#define SIZETIMEFMT 250
280 300
@@ -293,7 +313,7 @@ static int os_date (lua_State *L) {
293 stm = l_localtime(&t, &tmr); 313 stm = l_localtime(&t, &tmr);
294 if (stm == NULL) /* invalid date? */ 314 if (stm == NULL) /* invalid date? */
295 return luaL_error(L, 315 return luaL_error(L,
296 "time result cannot be represented in this installation"); 316 "date result cannot be represented in this installation");
297 if (strcmp(s, "*t") == 0) { 317 if (strcmp(s, "*t") == 0) {
298 lua_createtable(L, 0, 9); /* 9 = number of fields */ 318 lua_createtable(L, 0, 9); /* 9 = number of fields */
299 setallfields(L, stm); 319 setallfields(L, stm);
@@ -329,12 +349,12 @@ static int os_time (lua_State *L) {
329 struct tm ts; 349 struct tm ts;
330 luaL_checktype(L, 1, LUA_TTABLE); 350 luaL_checktype(L, 1, LUA_TTABLE);
331 lua_settop(L, 1); /* make sure table is at the top */ 351 lua_settop(L, 1); /* make sure table is at the top */
332 ts.tm_sec = getfield(L, "sec", 0, 0);
333 ts.tm_min = getfield(L, "min", 0, 0);
334 ts.tm_hour = getfield(L, "hour", 12, 0);
335 ts.tm_mday = getfield(L, "day", -1, 0);
336 ts.tm_mon = getfield(L, "month", -1, 1);
337 ts.tm_year = getfield(L, "year", -1, 1900); 352 ts.tm_year = getfield(L, "year", -1, 1900);
353 ts.tm_mon = getfield(L, "month", -1, 1);
354 ts.tm_mday = getfield(L, "day", -1, 0);
355 ts.tm_hour = getfield(L, "hour", 12, 0);
356 ts.tm_min = getfield(L, "min", 0, 0);
357 ts.tm_sec = getfield(L, "sec", 0, 0);
338 ts.tm_isdst = getboolfield(L, "isdst"); 358 ts.tm_isdst = getboolfield(L, "isdst");
339 t = mktime(&ts); 359 t = mktime(&ts);
340 setallfields(L, &ts); /* update fields with normalized values */ 360 setallfields(L, &ts); /* update fields with normalized values */