From e58cc264e32bfcf968847e3eec68d07fcc170390 Mon Sep 17 00:00:00 2001
From: Xing Guo <higuoxing@gmail.com>
Date: Thu, 9 Apr 2026 11:00:54 +0800
Subject: [PATCH] Use mul_size for allocation products potentially to overflow

Several call sites multiplied runtime factors before palloc; use mul_size()
in the backend and pg_mul_size_overflow() in the frontend gzip allocator.
---
 src/backend/backup/basebackup_gzip.c | 3 ++-
 src/backend/catalog/namespace.c      | 3 ++-
 src/backend/storage/buffer/bufmgr.c  | 4 +++-
 src/backend/utils/adt/tsgistidx.c    | 7 ++++---
 src/fe_utils/astreamer_gzip.c        | 8 +++++++-
 5 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/src/backend/backup/basebackup_gzip.c b/src/backend/backup/basebackup_gzip.c
index c5e4c4143e8..1ec2c13ea7f 100644
--- a/src/backend/backup/basebackup_gzip.c
+++ b/src/backend/backup/basebackup_gzip.c
@@ -17,6 +17,7 @@
 #endif
 
 #include "backup/basebackup_sink.h"
+#include "storage/shmem.h"
 
 #ifdef HAVE_LIBZ
 typedef struct bbsink_gzip
@@ -297,7 +298,7 @@ bbsink_gzip_manifest_contents(bbsink *sink, size_t len)
 static void *
 gzip_palloc(void *opaque, unsigned items, unsigned size)
 {
-	return palloc(items * size);
+	return palloc(mul_size(size, items));
 }
 
 /*
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 56b87d878e8..d251cd302ff 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -48,6 +48,7 @@
 #include "nodes/makefuncs.h"
 #include "storage/ipc.h"
 #include "storage/lmgr.h"
+#include "storage/shmem.h"
 #include "storage/proc.h"
 #include "storage/procarray.h"
 #include "utils/acl.h"
@@ -1994,7 +1995,7 @@ OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok,
 							  2 * sizeof(Oid))
 
 	if (catlist->n_members > 0)
-		resultSpace = palloc(catlist->n_members * SPACE_PER_OP);
+		resultSpace = palloc(mul_size(SPACE_PER_OP, catlist->n_members));
 
 	for (i = 0; i < catlist->n_members; i++)
 	{
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 3cc0b0bdd92..b738c053830 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -62,6 +62,7 @@
 #include "storage/proclist.h"
 #include "storage/procsignal.h"
 #include "storage/read_stream.h"
+#include "storage/shmem.h"
 #include "storage/smgr.h"
 #include "storage/standby.h"
 #include "utils/memdebug.h"
@@ -4925,7 +4926,8 @@ DropRelationsAllBuffers(SMgrRelation *smgr_reln, int nlocators)
 	 * forks.
 	 */
 	block = (BlockNumber (*)[MAX_FORKNUM + 1])
-		palloc(sizeof(BlockNumber) * n * (MAX_FORKNUM + 1));
+		palloc(mul_size(mul_size(sizeof(BlockNumber), (MAX_FORKNUM + 1)),
+						n));
 
 	/*
 	 * We can avoid scanning the entire buffer pool if we know the exact size
diff --git a/src/backend/utils/adt/tsgistidx.c b/src/backend/utils/adt/tsgistidx.c
index e35a25797a0..38a80ad72d2 100644
--- a/src/backend/utils/adt/tsgistidx.c
+++ b/src/backend/utils/adt/tsgistidx.c
@@ -18,6 +18,7 @@
 #include "access/heaptoast.h"
 #include "access/reloptions.h"
 #include "common/int.h"
+#include "storage/shmem.h"
 #include "lib/qunique.h"
 #include "port/pg_bitutils.h"
 #include "tsearch/ts_utils.h"
@@ -625,7 +626,7 @@ gtsvector_picksplit(PG_FUNCTION_ARGS)
 				size_beta;
 	int32		size_waste,
 				waste = -1;
-	int32		nbytes;
+	Size		nbytes;
 	OffsetNumber seed_1 = 0,
 				seed_2 = 0;
 	OffsetNumber *left,
@@ -638,12 +639,12 @@ gtsvector_picksplit(PG_FUNCTION_ARGS)
 	SPLITCOST  *costvector;
 
 	maxoff = entryvec->n - 2;
-	nbytes = (maxoff + 2) * sizeof(OffsetNumber);
+	nbytes = mul_size(sizeof(OffsetNumber), (maxoff + 2));
 	v->spl_left = (OffsetNumber *) palloc(nbytes);
 	v->spl_right = (OffsetNumber *) palloc(nbytes);
 
 	cache = palloc_array(CACHESIGN, maxoff + 2);
-	cache_sign = palloc(siglen * (maxoff + 2));
+	cache_sign = palloc(mul_size(siglen, (maxoff + 2)));
 
 	for (j = 0; j < maxoff + 2; j++)
 		cache[j].sign = &cache_sign[siglen * j];
diff --git a/src/fe_utils/astreamer_gzip.c b/src/fe_utils/astreamer_gzip.c
index bc3d53076e1..ffc41a75219 100644
--- a/src/fe_utils/astreamer_gzip.c
+++ b/src/fe_utils/astreamer_gzip.c
@@ -32,6 +32,7 @@
 #include <zlib.h>
 #endif
 
+#include "common/int.h"
 #include "common/logging.h"
 #include "fe_utils/astreamer.h"
 
@@ -382,7 +383,12 @@ astreamer_gzip_decompressor_free(astreamer *streamer)
 static void *
 gzip_palloc(void *opaque, unsigned items, unsigned size)
 {
-	return palloc(items * size);
+	size_t nbytes;
+
+	if (pg_mul_size_overflow((size_t) size, (size_t) items, &nbytes))
+		pg_fatal("gzip library requested invalid allocation size");
+
+	return palloc(nbytes);
 }
 
 /*
-- 
2.50.1 (Apple Git-155)

