]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Avoid overflow in size calculations in formatting.c.
authorNathan Bossart <nathan@postgresql.org>
Mon, 11 May 2026 12:13:47 +0000 (05:13 -0700)
committerNoah Misch <noah@leadboat.com>
Mon, 11 May 2026 12:13:47 +0000 (05:13 -0700)
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

src/backend/utils/adt/formatting.c

index 9a8c99336b521b45e3552850f4187394d5486aae..79cef8facfd0622f5917ff3e4d1a32044192eb51 100644 (file)
@@ -3904,7 +3904,7 @@ datetime_to_char_body(TmToChar *tmtc, const text *fmt, bool is_interval, Oid col
        /*
         * 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)
@@ -3915,7 +3915,7 @@ datetime_to_char_body(TmToChar *tmtc, const text *fmt, bool is_interval, Oid col
                 */
                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);
@@ -4330,7 +4330,7 @@ datetime_format_has_tz(const char *fmt_str)
                 */
                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);
@@ -4417,7 +4417,7 @@ do_to_timestamp(const text *date_txt, const 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);
@@ -4953,7 +4953,7 @@ NUM_cache(int len, NUMDesc *Num, const 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;