From b2b3d5d184455acdc3cd91d083a0d2403af6c847 Mon Sep 17 00:00:00 2001 From: "Thomas G. Lockhart" Date: Thu, 15 Apr 1999 02:22:39 +0000 Subject: [PATCH] Fix code to check legal dates *before* calling localtime() to get the time zone. Previously, localtime() rotated a date with a day of month field which exceeded the actual range into the next months, masking the fact that a bad date had been specified. Regression tests pass. --- src/backend/utils/adt/datetime.c | 36 +-------- src/backend/utils/adt/dt.c | 130 ++++++++++--------------------- 2 files changed, 43 insertions(+), 123 deletions(-) diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index c0fcf54e05..bdc4b589d2 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.30 1999/03/14 16:40:15 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.31 1999/04/15 02:22:37 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -27,19 +27,6 @@ static int date2tm(DateADT dateVal, int *tzp, struct tm * tm, double *fsec, char **tzn); -#define UTIME_MINYEAR (1901) -#define UTIME_MINMONTH (12) -#define UTIME_MINDAY (14) -#define UTIME_MAXYEAR (2038) -#define UTIME_MAXMONTH (01) -#define UTIME_MAXDAY (18) - -#define IS_VALID_UTIME(y,m,d) (((y > UTIME_MINYEAR) \ - || ((y == UTIME_MINYEAR) && ((m > UTIME_MINMONTH) \ - || ((m == UTIME_MINMONTH) && (d >= UTIME_MINDAY))))) \ - && ((y < UTIME_MAXYEAR) \ - || ((y == UTIME_MAXYEAR) && ((m < UTIME_MAXMONTH) \ - || ((m == UTIME_MAXMONTH) && (d <= UTIME_MAXDAY)))))) /***************************************************************************** * Date ADT @@ -71,7 +58,7 @@ date_in(char *str) #endif if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) || (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp) != 0)) - elog(ERROR, "Bad date external representation %s", str); + elog(ERROR, "Bad date external representation '%s'", str); switch (dtype) { @@ -89,19 +76,9 @@ date_in(char *str) break; default: - elog(ERROR, "Unrecognized date external representation %s", str); + elog(ERROR, "Unrecognized date external representation '%s'", str); } -#ifdef NOT_USED - if (tm->tm_year < 0 || tm->tm_year > 32767) - elog(ERROR, "date_in: year must be limited to values 0 through 32767 in '%s'", str); - if (tm->tm_mon < 1 || tm->tm_mon > 12) - elog(ERROR, "date_in: month must be limited to values 1 through 12 in '%s'", str); -#endif - if (tm->tm_mday < 1 || tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]) - elog(ERROR, "date_in: day must be limited to values 1 through %d in '%s'", - day_tab[isleap(tm->tm_year)][tm->tm_mon - 1], str); - date = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1)); return date; @@ -453,13 +430,6 @@ time_in(char *str) || (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec) != 0)) elog(ERROR, "Bad time external representation '%s'", str); - if ((tm->tm_hour < 0) || (tm->tm_hour > 23)) - elog(ERROR, "Hour must be limited to values 0 through 23 in '%s'", str); - if ((tm->tm_min < 0) || (tm->tm_min > 59)) - elog(ERROR, "Minute must be limited to values 0 through 59 in '%s'", str); - if ((tm->tm_sec < 0) || ((tm->tm_sec + fsec) >= 60)) - elog(ERROR, "Second must be limited to values 0 through < 60 in '%s'", str); - time = palloc(sizeof(TimeADT)); *time = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec); diff --git a/src/backend/utils/adt/dt.c b/src/backend/utils/adt/dt.c index 17a1250928..373553ed4c 100644 --- a/src/backend/utils/adt/dt.c +++ b/src/backend/utils/adt/dt.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.67 1999/03/20 02:31:45 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.68 1999/04/15 02:22:39 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -55,12 +55,6 @@ static int tm2timespan(struct tm * tm, double fsec, TimeSpan *span); #define USE_DATE_CACHE 1 #define ROUND_ALL 0 -#if 0 -#define isleap(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0))) - -int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}; -#endif - int day_tab[2][13] = { {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}, {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}}; @@ -882,15 +876,6 @@ datetime_pl_span(DateTime *datetime, TimeSpan *span) } /* adjust for end of month boundary problems... */ -#if 0 - if (tm->tm_mday > mdays[tm->tm_mon - 1]) - { - if ((tm->tm_mon == 2) && isleap(tm->tm_year)) - tm->tm_mday = (mdays[tm->tm_mon - 1] + 1); - else - tm->tm_mday = mdays[tm->tm_mon - 1]; - } -#endif if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]) tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]); @@ -1197,21 +1182,11 @@ datetime_age(DateTime *datetime1, DateTime *datetime2) { if (dt1 < dt2) { -#if 0 - tm->tm_mday += mdays[tm1->tm_mon - 1]; - if (isleap(tm1->tm_year) && (tm1->tm_mon == 2)) - tm->tm_mday++; -#endif tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1]; tm->tm_mon--; } else { -#if 0 - tm->tm_mday += mdays[tm2->tm_mon - 1]; - if (isleap(tm2->tm_year) && (tm2->tm_mon == 2)) - tm->tm_mday++; -#endif tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1]; tm->tm_mon--; } @@ -2302,21 +2277,6 @@ datetkn *deltacache[MAXDATEFIELDS] = {NULL}; * These routines will be used by other date/time packages - tgl 97/02/25 */ -#if 0 -XXX moved to dt.h - thomas 1999-01-15 -/* Set the minimum year to one greater than the year of the first valid day - * to avoid having to check year and day both. - tgl 97/05/08 - */ - -#define JULIAN_MINYEAR (-4713) -#define JULIAN_MINMONTH (11) -#define JULIAN_MINDAY (23) - -#define IS_VALID_JULIAN(y,m,d) ((y > JULIAN_MINYEAR) \ - || ((y == JULIAN_MINYEAR) && ((m > JULIAN_MINMONTH) \ - || ((m == JULIAN_MINMONTH) && (d >= JULIAN_MINDAY))))) -#endif - int date2j(int y, int m, int d) { @@ -3063,47 +3023,55 @@ DecodeDateTime(char **field, int *ftype, int nf, printf(" %02d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec); #endif - if ((*dtype == DTK_DATE) && ((fmask & DTK_DATE_M) != DTK_DATE_M)) - return ((fmask & DTK_TIME_M) == DTK_TIME_M) ? 1 : -1; - - /* timezone not specified? then find local timezone if possible */ - if ((*dtype == DTK_DATE) && ((fmask & DTK_DATE_M) == DTK_DATE_M) - && (tzp != NULL) && (!(fmask & DTK_M(TZ)))) + /* do additional checking for full date specs... */ + if (*dtype == DTK_DATE) { + if ((fmask & DTK_DATE_M) != DTK_DATE_M) + return ((fmask & DTK_TIME_M) == DTK_TIME_M) ? 1 : -1; - /* - * daylight savings time modifier but no standard timezone? then - * error - */ - if (fmask & DTK_M(DTZMOD)) + /* check for valid day of month, now that we know for sure the month and year... */ + if ((tm->tm_mday < 1) + || (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])) return -1; - if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday)) + /* timezone not specified? then find local timezone if possible */ + if (((fmask & DTK_DATE_M) == DTK_DATE_M) + && (tzp != NULL) && (!(fmask & DTK_M(TZ)))) { + /* + * daylight savings time modifier but no standard timezone? then + * error + */ + if (fmask & DTK_M(DTZMOD)) + return -1; + + if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday)) + { #ifdef USE_POSIX_TIME - tm->tm_year -= 1900; - tm->tm_mon -= 1; - tm->tm_isdst = -1; - mktime(tm); - tm->tm_year += 1900; - tm->tm_mon += 1; + tm->tm_year -= 1900; + tm->tm_mon -= 1; + tm->tm_isdst = -1; + mktime(tm); + tm->tm_year += 1900; + tm->tm_mon += 1; #if defined(HAVE_TM_ZONE) - *tzp = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */ + *tzp = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */ #elif defined(HAVE_INT_TIMEZONE) - *tzp = ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone); + *tzp = ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone); #else #error USE_POSIX_TIME is defined but neither HAVE_TM_ZONE or HAVE_INT_TIMEZONE are defined #endif #else /* !USE_POSIX_TIME */ - *tzp = CTimeZone; + *tzp = CTimeZone; #endif - } - else - { - tm->tm_isdst = 0; - *tzp = 0; + } + else + { + tm->tm_isdst = 0; + *tzp = 0; + } } } @@ -3231,6 +3199,11 @@ DecodeTimeOnly(char **field, int *ftype, int nf, int *dtype, struct tm * tm, dou else if ((mer == PM) && (tm->tm_hour != 12)) tm->tm_hour += 12; + if (((tm->tm_hour < 0) || (tm->tm_hour > 23)) + || ((tm->tm_min < 0) || (tm->tm_min > 59)) + || ((tm->tm_sec < 0) || ((tm->tm_sec + *fsec) >= 60))) + return -1; + if ((fmask & DTK_TIME_M) != DTK_TIME_M) return -1; @@ -3541,15 +3514,6 @@ DecodeNumber(int flen, char *str, int fmask, tm->tm_year = val; /* adjust ONLY if exactly two digits... */ -#if 0 - if (flen == 2) - { - if (tm->tm_year < 70) - tm->tm_year += 2000; - else if (tm->tm_year < 100) - tm->tm_year += 1900; - } -#endif *is2digits = (flen == 2); } @@ -3615,13 +3579,6 @@ DecodeNumberField(int len, char *str, int fmask, tm->tm_mon = atoi(str + 2); *(str + 2) = '\0'; tm->tm_year = atoi(str + 0); - -#if 0 - if (tm->tm_year < 70) - tm->tm_year += 2000; - else if (tm->tm_year < 100) - tm->tm_year += 1900; -#endif *is2digits = TRUE; } @@ -3636,13 +3593,6 @@ DecodeNumberField(int len, char *str, int fmask, *(str + 2) = '\0'; tm->tm_mon = 1; tm->tm_year = atoi(str + 0); - -#if 0 - if (tm->tm_year < 70) - tm->tm_year += 2000; - else if (tm->tm_year < 100) - tm->tm_year += 1900; -#endif *is2digits = TRUE; } else if (strchr(str, '.') != NULL) -- GitLab