Skip to content

Commit 6e5a39c

Browse files
committed
Reject out-of-range numeric timezone specifications.
In commit 631dc39, we started to handle simple numeric timezone offsets via the zic library instead of the old CTimeZone/HasCTZSet kluge. However, we overlooked the fact that the zic code will reject UTC offsets exceeding a week (which seems a bit arbitrary, but not because it's too tight ...). This led to possibly setting session_timezone to NULL, which results in crashes in most timezone-related operations as of 9.4, and crashes in a small number of places even before that. So check for NULL return from pg_tzset_offset() and report an appropriate error message. Per bug #11014 from Duncan Gillis. Back-patch to all supported branches, like the previous patch. (Unfortunately, as of today that no longer includes 8.4.)
1 parent 391aa8a commit 6e5a39c

File tree

2 files changed

+37
-11
lines changed

2 files changed

+37
-11
lines changed

src/backend/commands/variable.c

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,8 @@ assign_timezone(const char *value, bool doit, GucSource source)
241241
char *result;
242242
char *endptr;
243243
double hours;
244+
int new_ctimezone;
245+
pg_tz *new_tz;
244246

245247
/*
246248
* Check for INTERVAL 'foo'
@@ -294,16 +296,28 @@ assign_timezone(const char *value, bool doit, GucSource source)
294296
pfree(interval);
295297
return NULL;
296298
}
297-
if (doit)
298-
{
299-
/* Here we change from SQL to Unix sign convention */
299+
300+
/* Here we change from SQL to Unix sign convention */
300301
#ifdef HAVE_INT64_TIMESTAMP
301-
CTimeZone = -(interval->time / USECS_PER_SEC);
302+
new_ctimezone = -(interval->time / USECS_PER_SEC);
302303
#else
303-
CTimeZone = -interval->time;
304+
new_ctimezone = -interval->time;
304305
#endif
305-
session_timezone = pg_tzset_offset(CTimeZone);
306+
new_tz = pg_tzset_offset(new_ctimezone);
306307

308+
if (!new_tz)
309+
{
310+
ereport(GUC_complaint_elevel(source),
311+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
312+
errmsg("invalid interval value for time zone: out of range")));
313+
pfree(interval);
314+
return NULL;
315+
}
316+
317+
if (doit)
318+
{
319+
CTimeZone = new_ctimezone;
320+
session_timezone = new_tz;
307321
HasCTZSet = true;
308322
}
309323
pfree(interval);
@@ -316,11 +330,22 @@ assign_timezone(const char *value, bool doit, GucSource source)
316330
hours = strtod(value, &endptr);
317331
if (endptr != value && *endptr == '\0')
318332
{
333+
/* Here we change from SQL to Unix sign convention */
334+
new_ctimezone = -hours * SECS_PER_HOUR;
335+
new_tz = pg_tzset_offset(new_ctimezone);
336+
337+
if (!new_tz)
338+
{
339+
ereport(GUC_complaint_elevel(source),
340+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
341+
errmsg("invalid value for time zone: out of range")));
342+
return NULL;
343+
}
344+
319345
if (doit)
320346
{
321-
/* Here we change from SQL to Unix sign convention */
322-
CTimeZone = -hours * SECS_PER_HOUR;
323-
session_timezone = pg_tzset_offset(CTimeZone);
347+
CTimeZone = new_ctimezone;
348+
session_timezone = new_tz;
324349
HasCTZSet = true;
325350
}
326351
}
@@ -352,8 +377,6 @@ assign_timezone(const char *value, bool doit, GucSource source)
352377
/*
353378
* Otherwise assume it is a timezone name, and try to load it.
354379
*/
355-
pg_tz *new_tz;
356-
357380
new_tz = pg_tzset(value);
358381

359382
if (!new_tz)

src/timezone/pgtz.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,6 +1333,9 @@ pg_tzset(const char *name)
13331333
* The GMT offset is specified in seconds, positive values meaning west of
13341334
* Greenwich (ie, POSIX not ISO sign convention). However, we use ISO
13351335
* sign convention in the displayable abbreviation for the zone.
1336+
*
1337+
* Caution: this can fail (return NULL) if the specified offset is outside
1338+
* the range allowed by the zic library.
13361339
*/
13371340
pg_tz *
13381341
pg_tzset_offset(long gmtoffset)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy