From: Jason Baron <jbaron@redhat.com> Subject: [RHEL5 patch] fix tux overflow Date: Fri, 23 Mar 2007 10:51:40 -0400 (EDT) Bugzilla: 231561 Message-Id: <Pine.LNX.4.64.0703231049580.2638@dhcp83-20.boston.redhat.com> Changelog: [tux] date overflow fix fixes bz #231561 thanks, -jason --- linux-2.6.18.noarch/net/tux/times.c.bak 2007-03-22 16:59:01.000000000 -0400 +++ linux-2.6.18.noarch/net/tux/times.c 2007-03-22 16:59:15.000000000 -0400 @@ -30,8 +30,11 @@ #include <linux/slab.h> #include <linux/ctype.h> - -#include "times.h" +#define EPOCH_YEAR 1970 +#define DAY (24 * 60 * 60) +#define YEAR (365 * DAY) +#define LEAP_YEAR (YEAR + DAY) +#define FOUR_CYCLE (3 * YEAR + LEAP_YEAR) char *dayName[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" @@ -42,6 +45,33 @@ static char *monthName[12] = { "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +unsigned int month_table[2][12] = { + { 31 * DAY, + (31 + 28) * DAY, + (31 + 28 + 31) * DAY, + (31 + 28 + 31 + 30) * DAY, + (31 + 28 + 31 + 30 + 31) * DAY, + (31 + 28 + 31 + 30 + 31 + 30) * DAY, + (31 + 28 + 31 + 30 + 31 + 30 + 31) * DAY, + (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31) * DAY, + (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30) * DAY, + (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31) * DAY, + (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30) * DAY, + (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31) * DAY }, + { 31 * DAY, + (31 + 29) * DAY, + (31 + 29 + 31) * DAY, + (31 + 29 + 31 + 30) * DAY, + (31 + 29 + 31 + 30 + 31) * DAY, + (31 + 29 + 31 + 30 + 31 + 30) * DAY, + (31 + 29 + 31 + 30 + 31 + 30 + 31) * DAY, + (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31) * DAY, + (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30) * DAY, + (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31) * DAY, + (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30) * DAY, + (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31) * DAY }, +}; + char itoa_h[60]={'0','0','0','0','0','0','0','0','0','0', '1','1','1','1','1','1','1','1','1','1', '2','2','2','2','2','2','2','2','2','2', @@ -58,119 +88,56 @@ char itoa_l[60]={'0','1','2','3','4','5' int time_unix2ls(time_t zulu, char *buf) { - int Y=0,M=0,D=0; - int H=0,Min=0,S=0,WD=0; - int I,I2; - time_t rest, delta; + unsigned int i, year, month, day, hour, minute, leap_year, cycles, *mtp; + unsigned long offset; + time_t delta; - if (zulu > xtime.tv_sec) + if ((unsigned long)zulu > (unsigned long)xtime.tv_sec) zulu = xtime.tv_sec; - I=0; - while (I<TUX_NUMYEARS) { - if (TimeDays[I][0]>zulu) - break; - I++; - } - - Y=--I; - if (I<0) { - Y=0; - goto BuildYear; - } - I2=0; - while (I2<=12) { - if (TimeDays[I][I2]>zulu) - break; - I2++; - } - - M=I2-1; - - rest=zulu - TimeDays[Y][M]; - WD=WeekDays[Y][M]; - D=rest/86400; - rest=rest%86400; - WD+=D; - WD=WD%7; - H=rest/3600; - rest=rest%3600; - Min=rest/60; - rest=rest%60; - S=rest; + offset = (unsigned long)zulu; -BuildYear: - Y+=TUX_YEAROFFSET; + /* calculate the year */ + offset += YEAR + LEAP_YEAR; + year = EPOCH_YEAR - 2; + cycles = offset / FOUR_CYCLE; + offset -= cycles * FOUR_CYCLE; + year += 4 * cycles; + if (offset >= LEAP_YEAR) { + offset -= LEAP_YEAR; + i = offset / YEAR; + offset -= i * YEAR; + year += i + 1; + leap_year = 0; + } else + leap_year = 1; + /* next we calculate the month */ + mtp = &month_table[leap_year][0]; + for (i = 0; i < 11; i++, mtp++) { + if (offset < *mtp) + break; + } + month = i; + if (month != 0) + offset -= *(mtp - 1); + + /* finally, calculate day, hour, minute */ + day = offset / DAY; + offset -= day * DAY; + hour = offset / 3600; + offset -= hour * 3600; + minute = offset / 60; /* Format: Day, 01 Mon 1999 01:01:01 GMT */ - delta = xtime.tv_sec - zulu; - if (delta > 6*30*24*60) + if (delta > YEAR / 2) // "May 23 2000" - return sprintf( buf, "%s %02i %04i", monthName[M], D+1, Y); + return sprintf( buf, "%s %02i %04i", monthName[month], day + 1, year); else // "May 23 10:14" return sprintf( buf, "%s %02i %02i:%02i", - monthName[M], D+1, H, Min); -} - -static int MonthHash[32] = - {0,0,7,0,0,0,0,0,0,0,0,3,0,0,0,2,6,0,5,0,9,8,4,0,0,11,1,10,0,0,0,0}; - -#define is_digit(c) ((c) >= '0' && (c) <= '9') - -static inline int skip_atoi(char **s) -{ - int i=0; - - while (is_digit(**s)) - i = i*10 + *((*s)++) - '0'; - return i; -} - -time_t mimetime_to_unixtime(char *Q) -{ - int Y,M,D,H,Min,S; - unsigned int Hash; - time_t Temp; - char *s,**s2; - - s=Q; - s2=&s; - - if (strlen(s)<30) return 0; - if (s[3]!=',') return 0; - if (s[19]!=':') return 0; - - s+=5; /* Skip day of week */ - D = skip_atoi(s2); /* Day of month */ - s++; - Hash = (char)s[0]+(char)s[2]; - Hash = (Hash<<1) + (char)s[1]; - Hash = (Hash&63)>>1; - M = MonthHash[Hash]; - s+=4; - Y = skip_atoi(s2); /* Year */ - s++; - H = skip_atoi(s2); /* Hour */ - s++; - Min = skip_atoi(s2); /* Minutes */ - s++; - S = skip_atoi(s2); /* Seconds */ - s++; - if ((s[0]!='G')||(s[1]!='M')||(s[2]!='T')) - { - return 0; /* No GMT */ - } - - if (Y<TUX_YEAROFFSET) Y = TUX_YEAROFFSET; - if (Y>TUX_YEAROFFSET+9) Y = TUX_YEAROFFSET+9; - - Temp = TimeDays[Y-TUX_YEAROFFSET][M]; - Temp += D*86400+H*3600+Min*60+S; - - return Temp; + monthName[month], day + 1, hour, minute); } // writes the full http date, corresponding to time_t received --- linux-2.6.18.noarch/net/tux/times.h.bak 2007-03-22 16:59:01.000000000 -0400 +++ linux-2.6.18.noarch/net/tux/times.h 1969-12-31 19:00:00.000000000 -0500 @@ -1,26 +0,0 @@ -static time_t TimeDays[10][13] = { - { 852073200, 854751600, 857170800, 859849200, 862441200, 865119600, 867711600, 870390000, 873068400, 875660400, 878338800, 880930800, 883609200 } , - { 883609200, 886287600, 888706800, 891385200, 893977200, 896655600, 899247600, 901926000, 904604400, 907196400, 909874800, 912466800, 915145200 } , - { 915145200, 917823600, 920242800, 922921200, 925513200, 928191600, 930783600, 933462000, 936140400, 938732400, 941410800, 944002800, 946681200 } , - { 946681200, 949359600, 951865200, 954543600, 957135600, 959814000, 962406000, 965084400, 967762800, 970354800, 973033200, 975625200, 978303600 } , - { 978303600, 980982000, 983401200, 986079600, 988671600, 991350000, 993942000, 996620400, 999298800, 1001890800, 1004569200, 1007161200, 1009839600 } , - { 1009839600, 1012518000, 1014937200, 1017615600, 1020207600, 1022886000, 1025478000, 1028156400, 1030834800, 1033426800, 1036105200, 1038697200, 1041375600 } , - { 1041375600, 1044054000, 1046473200, 1049151600, 1051743600, 1054422000, 1057014000, 1059692400, 1062370800, 1064962800, 1067641200, 1070233200, 1072911600 } , - { 1072911600, 1075590000, 1078095600, 1080774000, 1083366000, 1086044400, 1088636400, 1091314800, 1093993200, 1096585200, 1099263600, 1101855600, 1104534000 } , - { 1104534000, 1107212400, 1109631600, 1112310000, 1114902000, 1117580400, 1120172400, 1122850800, 1125529200, 1128121200, 1130799600, 1133391600, 1136070000 } , - { 1136070000, 1138748400, 1141167600, 1143846000, 1146438000, 1149116400, 1151708400, 1154386800, 1157065200, 1159657200, 1162335600, 1164927600, 1167606000 } -}; -static int WeekDays[10][13] = { - { 3, 6, 6, 2, 4, 0, 2, 5, 1, 3, 6, 1, 4 } , - { 4, 0, 0, 3, 5, 1, 3, 6, 2, 4, 0, 2, 5 } , - { 5, 1, 1, 4, 6, 2, 4, 0, 3, 5, 1, 3, 6 } , - { 6, 2, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5, 1 } , - { 1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6, 2 } , - { 2, 5, 5, 1, 3, 6, 1, 4, 0, 2, 5, 0, 3 } , - { 3, 6, 6, 2, 4, 0, 2, 5, 1, 3, 6, 1, 4 } , - { 4, 0, 1, 4, 6, 2, 4, 0, 3, 5, 1, 3, 6 } , - { 6, 2, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4, 0 } , - { 0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5, 1 } -}; -#define TUX_YEAROFFSET 1997 -#define TUX_NUMYEARS 10