From 12a6206864a0ba38dc506644bdb3928beea5256a Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 10 Aug 2026 06:38:17 -0700 Subject: [PATCH] Guard against overlength time zone abbreviations in to_char(). While typical abbreviations are only a few bytes long, a user-supplied time_zone setting could specify a much longer abbreviation, enough to overflow to_char's allocation of 12 bytes per format character. If so, throw an error in the same style as commit 9241c84cb (CVE-2015-0241). Reported-by: Hcamael Reported-by: Amjad Shahzad Reported-by: Tan Zhen of AntAISecurityLab Reported-by: Tomer Fichman Reported-by: Zheng Yu Reported-by: Amy Burnett (OpenAI Codex Security) Reported-by: Rick de Jager Reported-by: Heewon Song Reported-by: Sylvie Mayer Reported-by: Aleksander Alekseev Reported-by: Hillai Ben Sasson Author: Tom Lane Backpatch-through: 14 Security: CVE-2026-14669 --- src/backend/utils/adt/formatting.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c index 54213afb05a..d9183509aa0 100644 --- a/src/backend/utils/adt/formatting.c +++ b/src/backend/utils/adt/formatting.c @@ -2996,10 +2996,18 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col INVALID_FOR_INTERVAL; if (tmtcTzn(in)) { - /* We assume here that timezone names aren't localized */ + /* + * We assume here that timezone abbreviations aren't + * localized, so ASCII-only downcasing is sufficient. + */ char *p = asc_tolower_z(tmtcTzn(in)); - strcpy(s, p); + if (strlen(p) <= n->key->len * DCH_MAX_ITEM_SIZ) + strcpy(s, p); + else + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("time zone format value too long"))); pfree(p); s += strlen(s); } @@ -3008,7 +3016,14 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col INVALID_FOR_INTERVAL; if (tmtcTzn(in)) { - strcpy(s, tmtcTzn(in)); + const char *p = tmtcTzn(in); + + if (strlen(p) <= n->key->len * DCH_MAX_ITEM_SIZ) + strcpy(s, p); + else + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("time zone format value too long"))); s += strlen(s); } break;