Avoid overflow in size calculations in formatting.c.

A few functions in this file were incautious about multiplying a
possibly large integer by a factor more than 1 and then using it as
an allocation size.  This is harmless on 64-bit systems where we'd
compute a size exceeding MaxAllocSize and then fail, but on 32-bit
systems we could overflow size_t, leading to an undersized
allocation and buffer overrun.  To fix, use palloc_array() or
mul_size() instead of handwritten multiplication.

Reported-by: Sven Klemm <sven@tigerdata.com>
Reported-by: Xint Code
Author: Nathan Bossart <nathandbossart@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Tatsuo Ishii <ishii@postgresql.org>
Security: CVE-2026-6473
Backpatch-through: 14
This commit is contained in:
Nathan Bossart 2026-05-11 05:13:50 -07:00 committed by Noah Misch
parent 08c397b023
commit 137013f608

View file

@ -4070,7 +4070,7 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval, Oid collid)
/*
* Allocate workspace for result as C string
*/
result = palloc((fmt_len * DCH_MAX_ITEM_SIZ) + 1);
result = palloc(mul_size(fmt_len, DCH_MAX_ITEM_SIZ) + 1);
*result = '\0';
if (fmt_len > DCH_CACHE_SIZE)
@ -4081,7 +4081,7 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval, Oid collid)
*/
incache = false;
format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
format = palloc_array(FormatNode, fmt_len + 1);
parse_format(format, fmt_str, DCH_keywords,
DCH_suff, DCH_index, DCH_FLAG, NULL);
@ -4553,7 +4553,7 @@ do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
* Allocate new memory if format picture is bigger than static
* cache and do not use cache (call parser always)
*/
format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
format = palloc_array(FormatNode, fmt_len + 1);
parse_format(format, fmt_str, DCH_keywords, DCH_suff, DCH_index,
DCH_FLAG | (std ? STD_FLAG : 0), NULL);
@ -4993,7 +4993,7 @@ NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree)
* Allocate new memory if format picture is bigger than static cache
* and do not use cache (call parser always)
*/
format = (FormatNode *) palloc((len + 1) * sizeof(FormatNode));
format = palloc_array(FormatNode, len + 1);
*shouldFree = true;