on BSDs, avoid seconds->date conversion that won't fit

On FreeBSD and related systems, calling localtime() on an out-of-range
value (e.g., where the year doesn't fit in 32 bits) still returns a
tm pointer, instead or returning NULL for an error. To avoid this
problem, restrict the argument to 51 bits (which seems like a lot
of bits, but is still confortably away from the overflow point).

Closes PR 14305
This commit is contained in:
Matthew Flatt 2014-01-24 06:51:04 -07:00
parent 018af7e809
commit 81ef1c876b
2 changed files with 19 additions and 2 deletions

View File

@ -417,6 +417,7 @@
# define USE_TM_GMTOFF_FIELD
# define USE_TM_ZONE_FIELD
# define MAX_VALID_DATE_SECONDS_BITS 51
# define MZ_JIT_USE_MPROTECT
@ -1072,6 +1073,7 @@
# define USE_TM_GMTOFF_FIELD
# define USE_TM_ZONE_FIELD
# define MAX_VALID_DATE_SECONDS_BITS 51
# define MZ_JIT_USE_MPROTECT
@ -1130,6 +1132,9 @@
/* TIME_TYPE_IS_UNSIGNED converts time_t values as unsigned. */
/* MAX_VALID_DATE_SECONDS_BITS sets a maximum number of bits for
seconds to pass to localtime() ro gmtime(). */
/* MIN_VALID_DATE_SECONDS sets a minimum vald time in seconds. */
/* PROCESS_FUNCTION adds (process ...) and (system ...) functions */

View File

@ -9344,11 +9344,23 @@ static int VALID_TIME_RANGE(UNBUNDLE_TIME_TYPE lnow)
return 1;
}
#else
# ifdef MIN_VALID_DATE_SECONDS
# define VALID_TIME_RANGE(x) ((x) >= MIN_VALID_DATE_SECONDS)
# define VALID_TIME_RANGE_MIN(x) ((x) >= MIN_VALID_DATE_SECONDS)
# else
# define VALID_TIME_RANGE(x) 1
# define VALID_TIME_RANGE_MIN(x) 1
# endif
# if defined(MAX_VALID_DATE_SECONDS_BITS) && defined(SIXTY_FOUR_BIT_INTEGERS)
# define VALID_TIME_RANGE_BITS(x) (((x) >= 0) \
? ((x) == ((x) & (((intptr_t)1 << MAX_VALID_DATE_SECONDS_BITS) - 1))) \
: ((-(x)) == ((-(x)) & (((intptr_t)1 << MAX_VALID_DATE_SECONDS_BITS) - 1))))
# else
# define VALID_TIME_RANGE_BITS(x) 1
# endif
# define VALID_TIME_RANGE(x) (VALID_TIME_RANGE_MIN(x) && VALID_TIME_RANGE_BITS(x))
#endif
static Scheme_Object *seconds_to_date(int argc, Scheme_Object **argv)