mktime bugs around the edges
Paul Eggert
eggert at lotl.twinsun.com
Sun Apr 3 21:32:06 UTC 1994
Here are some mktime bugs in tz-1994e.
(Bugs that PCTS should have caught :-)
mktime fails on the earliest representable time (Fri Dec 13 20:45:52 1901 GMT).
mktime does not fail, as it should, with one plus the last
representable time (i.e. with Tue Jan 19 03:14:08 2038 GMT).
It wraps around and reports Fri Dec 13 20:45:52 1901 GMT instead.
When normalizing times, mktime assumes that every minute contains 60
seconds. This is incorrect if leap seconds are in use.
mktime does not detect arithmetic overflow when normalizing
nonsensically large inputs.
Here is a patch.
===================================================================
RCS file: localtime.c,v
retrieving revision 1994.5.1.1
retrieving revision 1994.5.1.2
diff -c2 -r1994.5.1.1 -r1994.5.1.2
*** localtime.c 1994/04/03 02:54:41 1994.5.1.1
--- localtime.c 1994/04/03 21:25:32 1994.5.1.2
***************
*** 114,118 ****
static void localsub P((const time_t * timep, long offset,
struct tm * tmp));
! static void normalize P((int * tensptr, int * unitsptr, int base));
static void settzname P((void));
static time_t time1 P((struct tm * tmp,
--- 114,120 ----
static void localsub P((const time_t * timep, long offset,
struct tm * tmp));
! static int increment_overflow P((int * number, int delta));
! static int normalize_overflow P((int * tensptr, int * unitsptr,
! int base));
static void settzname P((void));
static time_t time1 P((struct tm * tmp,
***************
*** 1155,1160 ****
*/
! static void
! normalize(tensptr, unitsptr, base)
int * const tensptr;
int * const unitsptr;
--- 1157,1172 ----
*/
! static int
! increment_overflow(number, delta)
! int * number;
! int delta;
! {
! int number0 = *number;
! *number = number0 + delta;
! return (*number < number0) != (delta < 0);
! }
!
! static int
! normalize_overflow(tensptr, unitsptr, base)
int * const tensptr;
int * const unitsptr;
***************
*** 1166,1171 ****
(*unitsptr / base) :
(-1 - (-1 - *unitsptr) / base);
- *tensptr += tensdelta;
*unitsptr -= tensdelta * base;
}
--- 1178,1183 ----
(*unitsptr / base) :
(-1 - (-1 - *unitsptr) / base);
*unitsptr -= tensdelta * base;
+ return increment_overflow(tensptr, tensdelta);
}
***************
*** 1204,1225 ****
*okayp = FALSE;
yourtm = *tmp;
! if (yourtm.tm_sec >= SECSPERMIN + 2 || yourtm.tm_sec < 0)
! normalize(&yourtm.tm_min, &yourtm.tm_sec, SECSPERMIN);
! normalize(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR);
! normalize(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY);
! normalize(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR);
while (yourtm.tm_mday <= 0) {
! --yourtm.tm_year;
! yourtm.tm_mday +=
! year_lengths[isleap(yourtm.tm_year + TM_YEAR_BASE)];
}
while (yourtm.tm_mday > DAYSPERLYEAR) {
! yourtm.tm_mday -=
! year_lengths[isleap(yourtm.tm_year + TM_YEAR_BASE)];
! ++yourtm.tm_year;
}
for ( ; ; ) {
! i = mon_lengths[isleap(yourtm.tm_year +
! TM_YEAR_BASE)][yourtm.tm_mon];
if (yourtm.tm_mday <= i)
break;
--- 1216,1236 ----
*okayp = FALSE;
yourtm = *tmp;
! if ( normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR)
! || normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)
! || normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR)
! || increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
! return WRONG;
while (yourtm.tm_mday <= 0) {
! if (increment_overflow(&yourtm.tm_year, -1))
! return WRONG;
! yourtm.tm_mday += year_lengths[isleap(yourtm.tm_year)];
}
while (yourtm.tm_mday > DAYSPERLYEAR) {
! yourtm.tm_mday -= year_lengths[isleap(yourtm.tm_year)];
! if (increment_overflow(&yourtm.tm_year, 1))
! return WRONG;
}
for ( ; ; ) {
! i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
if (yourtm.tm_mday <= i)
break;
***************
*** 1227,1235 ****
if (++yourtm.tm_mon >= MONSPERYEAR) {
yourtm.tm_mon = 0;
! ++yourtm.tm_year;
}
}
! saved_seconds = yourtm.tm_sec;
! yourtm.tm_sec = 0;
/*
** Calculate the number of magnitude bits in a time_t
--- 1238,1264 ----
if (++yourtm.tm_mon >= MONSPERYEAR) {
yourtm.tm_mon = 0;
! if (increment_overflow(&yourtm.tm_year, 1))
! return WRONG;
}
}
! if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))
! return WRONG;
! if (yourtm.tm_year < EPOCH_YEAR - TM_YEAR_BASE) {
! /*
! ** We can't set tm_sec to 0, because that might push the
! ** time below the minimum representable time.
! ** Set tm_sec to 59 instead.
! ** This assumes that the minimum representable time is
! ** not in the same minute that a leap second was deleted from,
! ** which is a safer assumption than using 58 would be.
! */
! if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
! return WRONG;
! saved_seconds = yourtm.tm_sec;
! yourtm.tm_sec = SECSPERMIN - 1;
! } else {
! saved_seconds = yourtm.tm_sec;
! yourtm.tm_sec = 0;
! }
/*
** Calculate the number of magnitude bits in a time_t
***************
*** 1298,1302 ****
}
label:
! t += saved_seconds;
(*funcp)(&t, offset, tmp);
*okayp = TRUE;
--- 1327,1334 ----
}
label:
! newt = t + saved_seconds;
! if ((newt < t) != (saved_seconds < 0))
! return WRONG;
! t = newt;
(*funcp)(&t, offset, tmp);
*okayp = TRUE;
More information about the tz
mailing list