Expand the allowed range of timezone offsets to +/-15:59:59 from Greenwich.

We used to only allow offsets less than +/-13 hours, then it was +/14,
then it was +/-15.  That's still not good enough though, as per today's bug
report from Patric Bechtel.  This time I actually looked through the Olson
timezone database to find the largest offsets used anywhere.  The winners
are Asia/Manila, at -15:56:00 until 1844, and America/Metlakatla, at
+15:13:42 until 1867.  So we'd better allow offsets less than +/-16 hours.

Given the history, we are way overdue to have some greppable #define
symbols controlling this, so make some ... and also remove an obsolete
comment that didn't get fixed the last time.

Back-patch to all supported branches.
This commit is contained in:
Tom Lane 2012-05-30 19:58:35 -04:00
parent 07ab1383e3
commit cd0ff9c0f4
3 changed files with 14 additions and 7 deletions

View File

@ -1956,9 +1956,8 @@ timetz_recv(PG_FUNCTION_ARGS)
result->zone = pq_getmsgint(buf, sizeof(result->zone)); result->zone = pq_getmsgint(buf, sizeof(result->zone));
/* we allow GMT displacements up to 14:59:59, cf DecodeTimezone() */ /* Check for sane GMT displacement; see notes in datatype/timestamp.h */
if (result->zone <= -15 * SECS_PER_HOUR || if (result->zone <= -TZDISP_LIMIT || result->zone >= TZDISP_LIMIT)
result->zone >= 15 * SECS_PER_HOUR)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE), (errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
errmsg("time zone displacement out of range"))); errmsg("time zone displacement out of range")));

View File

@ -2698,9 +2698,6 @@ DecodeNumberField(int len, char *str, int fmask,
* Return 0 if okay (and set *tzp), a DTERR code if not okay. * Return 0 if okay (and set *tzp), a DTERR code if not okay.
* *
* NB: this must *not* ereport on failure; see commands/variable.c. * NB: this must *not* ereport on failure; see commands/variable.c.
*
* Note: we allow timezone offsets up to 13:59. There are places that
* use +1300 summer time.
*/ */
static int static int
DecodeTimezone(char *str, int *tzp) DecodeTimezone(char *str, int *tzp)
@ -2745,7 +2742,8 @@ DecodeTimezone(char *str, int *tzp)
else else
min = 0; min = 0;
if (hr < 0 || hr > 14) /* Range-check the values; see notes in datatype/timestamp.h */
if (hr < 0 || hr > MAX_TZDISP_HOUR)
return DTERR_TZDISP_OVERFLOW; return DTERR_TZDISP_OVERFLOW;
if (min < 0 || min >= MINS_PER_HOUR) if (min < 0 || min >= MINS_PER_HOUR)
return DTERR_TZDISP_OVERFLOW; return DTERR_TZDISP_OVERFLOW;

View File

@ -105,6 +105,16 @@ typedef struct
#define USECS_PER_MINUTE INT64CONST(60000000) #define USECS_PER_MINUTE INT64CONST(60000000)
#define USECS_PER_SEC INT64CONST(1000000) #define USECS_PER_SEC INT64CONST(1000000)
/*
* We allow numeric timezone offsets up to 15:59:59 either way from Greenwich.
* Currently, the record holders for wackiest offsets in actual use are zones
* Asia/Manila, at -15:56:00 until 1844, and America/Metlakatla, at +15:13:42
* until 1867. If we were to reject such values we would fail to dump and
* restore old timestamptz values with these zone settings.
*/
#define MAX_TZDISP_HOUR 15 /* maximum allowed hour part */
#define TZDISP_LIMIT ((MAX_TZDISP_HOUR + 1) * SECS_PER_HOUR)
/* /*
* DT_NOBEGIN represents timestamp -infinity; DT_NOEND represents +infinity * DT_NOBEGIN represents timestamp -infinity; DT_NOEND represents +infinity
*/ */