From aff71f87ba78e8fe5fb266ecfce692f2e23a5d6a Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 11 May 2026 05:13:49 -0700 Subject: [PATCH] Fix assorted places that need to use palloc_array(). multirange_recv and BlockRefTableReaderNextRelation 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. Fix these places by using palloc_array() instead of a handwritten multiplication. (In HEAD, some of them were fixed already, but none of that work got back-patched at the time.) In addition, BlockRefTableReaderNextRelation passes the same value to BlockRefTableRead's "int length" parameter. If built for 64-bit frontend code, palloc_array() allows a larger array size than it otherwise would, potentially allowing that parameter to overflow. Add an explicit check to forestall that and keep the behavior the same cross-platform. Reported-by: Xint Code Author: Tom Lane Backpatch-through: 14 Security: CVE-2026-6473 --- src/backend/utils/adt/multirangetypes.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/backend/utils/adt/multirangetypes.c b/src/backend/utils/adt/multirangetypes.c index 4c035911e92..5f98d856422 100644 --- a/src/backend/utils/adt/multirangetypes.c +++ b/src/backend/utils/adt/multirangetypes.c @@ -341,7 +341,7 @@ multirange_recv(PG_FUNCTION_ARGS) Oid mltrngtypoid = PG_GETARG_OID(1); int32 typmod = PG_GETARG_INT32(2); MultirangeIOData *cache; - uint32 range_count; + int32 range_count; RangeType **ranges; MultirangeType *ret; StringInfoData tmpbuf; @@ -349,7 +349,8 @@ multirange_recv(PG_FUNCTION_ARGS) cache = get_multirange_io_data(fcinfo, mltrngtypoid, IOFunc_receive); range_count = pq_getmsgint(buf, 4); - ranges = palloc(range_count * sizeof(RangeType *)); + /* palloc_array will enforce a more-or-less-sane range_count value */ + ranges = palloc_array(RangeType *, range_count); initStringInfo(&tmpbuf); for (int i = 0; i < range_count; i++) @@ -836,7 +837,7 @@ multirange_deserialize(TypeCacheEntry *rangetyp, { int i; - *ranges = palloc(*range_count * sizeof(RangeType *)); + *ranges = palloc_array(RangeType *, *range_count); for (i = 0; i < *range_count; i++) (*ranges)[i] = multirange_get_range(rangetyp, multirange, i); } @@ -1000,7 +1001,7 @@ multirange_constructor2(PG_FUNCTION_ARGS) deconstruct_array(rangeArray, rngtypid, rangetyp->typlen, rangetyp->typbyval, rangetyp->typalign, &elements, &nulls, &range_count); - ranges = palloc0(range_count * sizeof(RangeType *)); + ranges = palloc_array(RangeType *, range_count); for (i = 0; i < range_count; i++) { if (nulls[i])