From 303f3ea4e1bb0d39e1c758a01cbf2f126df5c09e Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@partin.io>
Date: Thu, 6 Aug 2026 15:45:30 +0000
Subject: [PATCH v1 1/3] Migrate array-like palloc() calls to palloc_array()

We have palloc_array() for callers to use a type-safe version of
palloc() that additionally does overflow checking. palloc_array() is the
preferred way to allocate arrays/buffers.

Signed-off-by: Tristan Partin <tristan@partin.io>
---
 contrib/btree_gist/btree_interval.c           |  2 +-
 contrib/btree_gist/btree_utils_num.c          | 12 ++---
 contrib/btree_gist/btree_uuid.c               |  2 +-
 contrib/dblink/dblink.c                       |  4 +-
 contrib/file_fdw/file_fdw.c                   |  4 +-
 contrib/fuzzystrmatch/dmetaphone.c            |  2 +-
 contrib/fuzzystrmatch/fuzzystrmatch.c         |  4 +-
 contrib/hstore/hstore_gin.c                   |  4 +-
 contrib/hstore/hstore_io.c                    | 16 +++---
 contrib/hstore/hstore_op.c                    | 18 +++----
 contrib/ltree/lquery_op.c                     |  4 +-
 contrib/ltree/ltree_io.c                      |  4 +-
 contrib/ltree/ltxtquery_io.c                  |  2 +-
 contrib/pageinspect/btreefuncs.c              |  4 +-
 contrib/pageinspect/ginfuncs.c                |  2 +-
 contrib/pg_logicalinspect/pg_logicalinspect.c |  4 +-
 contrib/pg_stash_advice/stashpersist.c        |  2 +-
 .../pg_stat_statements/pg_stat_statements.c   |  4 +-
 contrib/pg_trgm/trgm_gist.c                   |  2 +-
 contrib/pg_trgm/trgm_op.c                     |  4 +-
 contrib/pg_trgm/trgm_regexp.c                 |  5 +-
 contrib/pg_visibility/pg_visibility.c         |  2 +-
 contrib/pgcrypto/mbuf.c                       |  2 +-
 contrib/pgcrypto/pgcrypto.c                   |  2 +-
 contrib/pgcrypto/pgp-armor.c                  |  6 +--
 contrib/pgcrypto/px-hmac.c                    |  2 +-
 contrib/pgcrypto/px.c                         |  4 +-
 contrib/pgrowlocks/pgrowlocks.c               | 10 ++--
 contrib/postgres_fdw/connection.c             |  8 +--
 contrib/postgres_fdw/postgres_fdw.c           | 13 +++--
 contrib/seg/seg.c                             |  9 ++--
 contrib/tablefunc/tablefunc.c                 |  8 +--
 contrib/unaccent/unaccent.c                   |  2 +-
 contrib/xml2/xpath.c                          |  4 +-
 contrib/xml2/xslt_proc.c                      |  2 +-
 doc/src/sgml/xfunc.sgml                       |  8 +--
 src/backend/access/brin/brin_minmax_multi.c   |  4 +-
 src/backend/access/common/heaptuple.c         |  2 +-
 src/backend/access/common/printtup.c          |  3 +-
 src/backend/access/common/reloptions.c        |  6 +--
 src/backend/access/common/tupdesc.c           |  6 +--
 src/backend/access/gin/gindatapage.c          |  4 +-
 src/backend/access/gin/ginfast.c              |  2 +-
 src/backend/access/gin/ginget.c               |  8 +--
 src/backend/access/gin/gininsert.c            |  2 +-
 src/backend/access/gin/ginpostinglist.c       |  4 +-
 src/backend/access/gin/ginscan.c              | 10 ++--
 src/backend/access/gist/gistget.c             |  8 +--
 src/backend/access/gist/gistproc.c            | 10 ++--
 src/backend/access/gist/gistscan.c            |  8 +--
 src/backend/access/gist/gistsplit.c           | 12 ++---
 src/backend/access/gist/gistxlog.c            |  2 +-
 src/backend/access/heap/heapam.c              |  4 +-
 src/backend/access/heap/vacuumlazy.c          |  3 +-
 src/backend/access/nbtree/nbtinsert.c         |  4 +-
 src/backend/access/nbtree/nbtpreprocesskeys.c | 16 +++---
 src/backend/access/nbtree/nbtree.c            |  4 +-
 src/backend/access/spgist/spgdoinsert.c       |  2 +-
 src/backend/access/spgist/spgtextproc.c       |  2 +-
 src/backend/access/transam/multixact.c        |  2 +-
 src/backend/access/transam/twophase.c         |  4 +-
 src/backend/access/transam/xact.c             |  2 +-
 src/backend/access/transam/xlogreader.c       |  2 +-
 src/backend/access/transam/xlogrecovery.c     |  4 +-
 src/backend/backup/basebackup_incremental.c   |  2 +-
 src/backend/catalog/aclchk.c                  |  2 +-
 src/backend/catalog/heap.c                    |  2 +-
 src/backend/catalog/namespace.c               |  2 +-
 src/backend/catalog/pg_constraint.c           |  6 +--
 src/backend/catalog/pg_inherits.c             |  2 +-
 src/backend/catalog/pg_shdepend.c             |  3 +-
 src/backend/commands/alter.c                  | 18 +++----
 src/backend/commands/analyze.c                | 49 +++++++++----------
 src/backend/commands/collationcmds.c          |  2 +-
 src/backend/commands/copyfrom.c               | 24 ++++-----
 src/backend/commands/copyto.c                 |  4 +-
 src/backend/commands/dbcommands.c             |  2 +-
 src/backend/commands/explain.c                |  7 ++-
 src/backend/commands/explain_dr.c             |  2 +-
 src/backend/commands/explain_state.c          |  3 +-
 src/backend/commands/extension.c              |  8 +--
 src/backend/commands/functioncmds.c           | 14 +++---
 src/backend/commands/policy.c                 |  2 +-
 src/backend/commands/repack.c                 |  2 +-
 src/backend/commands/repack_worker.c          |  2 +-
 src/backend/commands/subscriptioncmds.c       |  6 +--
 src/backend/commands/tablecmds.c              |  5 +-
 src/backend/commands/tablespace.c             |  2 +-
 src/backend/commands/trigger.c                | 16 +++---
 src/backend/commands/tsearchcmds.c            |  2 +-
 src/backend/commands/vacuum.c                 |  2 +-
 src/backend/executor/execExpr.c               |  2 +-
 src/backend/executor/execExprInterp.c         | 12 ++---
 src/backend/executor/execGrouping.c           |  6 +--
 src/backend/executor/execJunk.c               |  4 +-
 src/backend/executor/execParallel.c           |  6 +--
 src/backend/executor/execSRF.c                |  4 +-
 src/backend/executor/execTuples.c             | 10 ++--
 src/backend/executor/execUtils.c              |  7 ++-
 src/backend/executor/functions.c              |  2 +-
 src/backend/executor/nodeAgg.c                | 24 ++++-----
 src/backend/executor/nodeAppend.c             |  9 ++--
 src/backend/executor/nodeBitmapAnd.c          |  2 +-
 src/backend/executor/nodeBitmapOr.c           |  2 +-
 src/backend/executor/nodeGather.c             |  3 +-
 src/backend/executor/nodeGatherMerge.c        |  9 ++--
 src/backend/executor/nodeIncrementalSort.c    |  4 +-
 src/backend/executor/nodeIndexscan.c          | 29 ++++-------
 src/backend/executor/nodeMemoize.c            |  6 +--
 src/backend/executor/nodeMergejoin.c          |  2 +-
 src/backend/executor/nodeModifyTable.c        |  2 +-
 src/backend/executor/nodeSetOp.c              |  3 +-
 src/backend/executor/nodeSubplan.c            | 14 +++---
 src/backend/executor/nodeTidscan.c            |  3 +-
 src/backend/executor/nodeValuesscan.c         |  6 +--
 src/backend/executor/nodeWindowAgg.c          |  4 +-
 src/backend/jit/llvm/llvmjit_expr.c           |  3 +-
 src/backend/lib/bipartite_match.c             |  8 +--
 src/backend/lib/knapsack.c                    |  4 +-
 src/backend/libpq/auth-scram.c                |  2 +-
 src/backend/libpq/hba.c                       |  4 +-
 src/backend/libpq/pqformat.c                  |  2 +-
 src/backend/nodes/queryjumblefuncs.c          |  5 +-
 src/backend/nodes/read.c                      |  2 +-
 src/backend/nodes/readfuncs.c                 |  4 +-
 src/backend/optimizer/path/allpaths.c         |  8 +--
 src/backend/optimizer/path/equivclass.c       |  3 +-
 src/backend/optimizer/path/pathkeys.c         |  4 +-
 src/backend/optimizer/plan/createplan.c       | 46 ++++++++---------
 src/backend/optimizer/plan/planner.c          | 22 ++++-----
 src/backend/optimizer/plan/setrefs.c          |  6 +--
 src/backend/optimizer/prep/prepjointree.c     | 15 ++----
 src/backend/optimizer/util/appendinfo.c       |  3 +-
 src/backend/optimizer/util/clauses.c          |  4 +-
 src/backend/optimizer/util/inherit.c          |  3 +-
 src/backend/optimizer/util/plancat.c          |  6 +--
 src/backend/optimizer/util/tlist.c            |  8 +--
 src/backend/parser/analyze.c                  |  5 +-
 src/backend/parser/parse_clause.c             |  5 +-
 src/backend/parser/parse_cte.c                |  2 +-
 src/backend/parser/parse_relation.c           |  6 +--
 src/backend/parser/parser.c                   |  2 +-
 src/backend/parser/scan.l                     |  4 +-
 src/backend/partitioning/partbounds.c         | 24 ++++-----
 src/backend/partitioning/partdesc.c           | 10 ++--
 src/backend/partitioning/partprune.c          | 11 ++---
 src/backend/postmaster/autovacuum.c           |  2 +-
 src/backend/postmaster/checkpointer.c         |  2 +-
 src/backend/postmaster/pmchild.c              |  2 +-
 src/backend/postmaster/postmaster.c           |  2 +-
 src/backend/replication/logical/snapbuild.c   |  2 +-
 src/backend/replication/logical/tablesync.c   |  2 +-
 src/backend/replication/logical/worker.c      |  2 +-
 src/backend/replication/pgoutput/pgoutput.c   |  2 +-
 src/backend/rewrite/rewriteHandler.c          |  4 +-
 src/backend/statistics/extended_stats.c       | 12 ++---
 src/backend/statistics/extended_stats_funcs.c |  2 +-
 src/backend/statistics/mcv.c                  |  4 +-
 src/backend/statistics/mvdistinct.c           |  3 +-
 src/backend/storage/buffer/bufmgr.c           |  2 +-
 src/backend/storage/ipc/dsm_impl.c            |  2 +-
 src/backend/storage/lmgr/deadlock.c           | 18 +++----
 src/backend/storage/lmgr/lock.c               |  2 +-
 src/backend/tcop/fastpath.c                   |  2 +-
 src/backend/tcop/postgres.c                   |  2 +-
 src/backend/tsearch/spell.c                   |  2 +-
 src/backend/tsearch/ts_parse.c                |  2 +-
 src/backend/tsearch/wparser_def.c             |  2 +-
 src/backend/utils/activity/pgstat_xact.c      |  3 +-
 src/backend/utils/adt/acl.c                   |  2 +-
 src/backend/utils/adt/array_typanalyze.c      |  4 +-
 src/backend/utils/adt/array_userfuncs.c       |  6 +--
 src/backend/utils/adt/arrayfuncs.c            | 30 ++++++------
 src/backend/utils/adt/arrayutils.c            |  2 +-
 src/backend/utils/adt/bool.c                  |  2 +-
 src/backend/utils/adt/bytea.c                 |  2 +-
 src/backend/utils/adt/char.c                  |  2 +-
 src/backend/utils/adt/datum.c                 |  8 +--
 src/backend/utils/adt/enum.c                  |  2 +-
 src/backend/utils/adt/float.c                 |  4 +-
 src/backend/utils/adt/format_type.c           |  2 +-
 src/backend/utils/adt/formatting.c            | 36 +++++++-------
 src/backend/utils/adt/int.c                   |  6 +--
 src/backend/utils/adt/jsonfuncs.c             | 10 ++--
 src/backend/utils/adt/jsonpath_scan.l         |  2 +-
 src/backend/utils/adt/levenshtein.c           |  4 +-
 src/backend/utils/adt/like_support.c          |  8 +--
 src/backend/utils/adt/lockfuncs.c             |  6 +--
 src/backend/utils/adt/mac.c                   |  2 +-
 src/backend/utils/adt/mac8.c                  |  2 +-
 src/backend/utils/adt/multirangetypes.c       | 10 ++--
 src/backend/utils/adt/name.c                  |  2 +-
 src/backend/utils/adt/numeric.c               | 12 ++---
 src/backend/utils/adt/oid.c                   |  4 +-
 src/backend/utils/adt/oracle_compat.c         |  8 +--
 src/backend/utils/adt/orderedsetaggs.c        | 20 ++++----
 src/backend/utils/adt/pg_locale.c             |  2 +-
 src/backend/utils/adt/pg_ndistinct.c          |  2 +-
 src/backend/utils/adt/rangetypes_typanalyze.c |  4 +-
 src/backend/utils/adt/regexp.c                |  2 +-
 src/backend/utils/adt/regproc.c               | 26 +++++-----
 src/backend/utils/adt/rowtypes.c              | 32 ++++++------
 src/backend/utils/adt/ruleutils.c             | 31 ++++++------
 src/backend/utils/adt/selfuncs.c              |  8 +--
 src/backend/utils/adt/timestamp.c             |  2 +-
 src/backend/utils/adt/tsquery.c               |  4 +-
 src/backend/utils/adt/tsquery_cleanup.c       |  2 +-
 src/backend/utils/adt/tsquery_rewrite.c       |  2 +-
 src/backend/utils/adt/tsvector.c              |  2 +-
 src/backend/utils/adt/tsvector_op.c           | 11 ++---
 src/backend/utils/adt/tsvector_parser.c       |  2 +-
 src/backend/utils/adt/varbit.c                |  6 +--
 src/backend/utils/adt/varchar.c               |  2 +-
 src/backend/utils/adt/varlena.c               |  8 +--
 src/backend/utils/adt/xid.c                   |  6 +--
 src/backend/utils/adt/xml.c                   |  4 +-
 src/backend/utils/cache/catcache.c            |  2 +-
 src/backend/utils/cache/inval.c               |  3 +-
 src/backend/utils/cache/lsyscache.c           |  2 +-
 src/backend/utils/cache/relcache.c            |  6 +--
 src/backend/utils/error/jsonlog.c             |  2 +-
 src/backend/utils/fmgr/funcapi.c              | 22 ++++-----
 src/backend/utils/sort/logtape.c              |  4 +-
 src/backend/utils/sort/tuplesort.c            |  8 +--
 src/backend/utils/sort/tuplesortvariants.c    | 14 ++----
 src/backend/utils/sort/tuplestore.c           |  5 +-
 src/backend/utils/time/snapmgr.c              |  6 +--
 src/bin/scripts/vacuuming.c                   |  2 +-
 src/common/blkreftable.c                      |  2 +-
 src/common/d2s.c                              |  2 +-
 src/common/f2s.c                              |  2 +-
 src/common/psprintf.c                         |  2 +-
 src/common/stringinfo.c                       |  2 +-
 src/include/lib/simplehash.h                  |  2 +-
 src/pl/plperl/plperl.c                        | 26 +++++-----
 src/pl/plpgsql/src/pl_gram.y                  |  2 +-
 src/pl/plpython/plpy_cursorobject.c           |  4 +-
 src/pl/plpython/plpy_exec.c                   |  6 +--
 src/pl/plpython/plpy_procedure.c              |  4 +-
 src/pl/plpython/plpy_spi.c                    |  4 +-
 src/pl/tcl/pltcl.c                            | 12 ++---
 .../ldap_password_func/ldap_password_func.c   |  2 +-
 src/test/modules/plsample/plsample.c          |  2 +-
 .../modules/spgist_name_ops/spgist_name_ops.c |  2 +-
 src/test/modules/test_aio/test_aio.c          | 10 ++--
 .../modules/test_binaryheap/test_binaryheap.c |  2 +-
 .../test_custom_types/test_custom_types.c     |  2 +-
 .../modules/test_integerset/test_integerset.c |  2 +-
 .../modules/test_radixtree/test_radixtree.c   |  2 +-
 src/test/modules/test_rbtree/test_rbtree.c    |  6 +--
 src/test/modules/test_regex/test_regex.c      |  2 +-
 .../test_resowner/test_resowner_basic.c       |  4 +-
 .../test_resowner/test_resowner_many.c        |  4 +-
 .../modules/test_saslprep/test_saslprep.c     |  2 +-
 .../modules/test_tidstore/test_tidstore.c     |  6 +--
 src/test/regress/regress.c                    | 18 +++----
 256 files changed, 742 insertions(+), 828 deletions(-)

diff --git a/contrib/btree_gist/btree_interval.c b/contrib/btree_gist/btree_interval.c
index 831662d3b9d..d671092ca41 100644
--- a/contrib/btree_gist/btree_interval.c
+++ b/contrib/btree_gist/btree_interval.c
@@ -148,7 +148,7 @@ gbt_intv_compress(PG_FUNCTION_ARGS)
 
 	if (entry->leafkey || INTERVALSIZE != sizeof(Interval))
 	{
-		char	   *r = (char *) palloc(2 * INTERVALSIZE);
+		char	   *r = palloc_array(char, 2 * INTERVALSIZE);
 
 		retval = palloc_object(GISTENTRY);
 
diff --git a/contrib/btree_gist/btree_utils_num.c b/contrib/btree_gist/btree_utils_num.c
index 971485dc8eb..e1f6d0fb2e1 100644
--- a/contrib/btree_gist/btree_utils_num.c
+++ b/contrib/btree_gist/btree_utils_num.c
@@ -31,7 +31,7 @@ gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo)
 			Cash		ch;
 		}			v;
 
-		GBT_NUMKEY *r = (GBT_NUMKEY *) palloc0(tinfo->indexsize);
+		GBT_NUMKEY *r = palloc0_array(GBT_NUMKEY, tinfo->indexsize);
 		void	   *leaf = NULL;
 
 		switch (tinfo->t)
@@ -374,12 +374,12 @@ gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
 	OffsetNumber i,
 				maxoff = entryvec->n - 1;
 	Nsrt	   *arr;
-	int			nbytes;
+	int			noffsets;
 
-	arr = (Nsrt *) palloc((maxoff + 1) * sizeof(Nsrt));
-	nbytes = (maxoff + 2) * sizeof(OffsetNumber);
-	v->spl_left = (OffsetNumber *) palloc(nbytes);
-	v->spl_right = (OffsetNumber *) palloc(nbytes);
+	arr = palloc_array(Nsrt, maxoff + 1);
+	noffsets = maxoff + 2;
+	v->spl_left = palloc_array(OffsetNumber, noffsets);
+	v->spl_right = palloc_array(OffsetNumber, noffsets);
 	v->spl_ldatum = PointerGetDatum(0);
 	v->spl_rdatum = PointerGetDatum(0);
 	v->spl_nleft = 0;
diff --git a/contrib/btree_gist/btree_uuid.c b/contrib/btree_gist/btree_uuid.c
index 36aaa85933c..354d6819b9e 100644
--- a/contrib/btree_gist/btree_uuid.c
+++ b/contrib/btree_gist/btree_uuid.c
@@ -105,7 +105,7 @@ gbt_uuid_compress(PG_FUNCTION_ARGS)
 
 	if (entry->leafkey)
 	{
-		char	   *r = (char *) palloc(2 * UUID_LEN);
+		char	   *r = palloc_array(char, 2 * UUID_LEN);
 		pg_uuid_t  *key = DatumGetUUIDP(entry->key);
 
 		retval = palloc_object(GISTENTRY);
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 9613f881985..59229d94202 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -3215,7 +3215,7 @@ appendSCRAMKeysInfo(StringInfo buf)
 
 	len = pg_b64_enc_len(sizeof(MyProcPort->scram_ClientKey));
 	/* don't forget the zero-terminator */
-	client_key = palloc0(len + 1);
+	client_key = palloc0_array(char, len + 1);
 	encoded_len = pg_b64_encode(MyProcPort->scram_ClientKey,
 								sizeof(MyProcPort->scram_ClientKey),
 								client_key, len);
@@ -3224,7 +3224,7 @@ appendSCRAMKeysInfo(StringInfo buf)
 
 	len = pg_b64_enc_len(sizeof(MyProcPort->scram_ServerKey));
 	/* don't forget the zero-terminator */
-	server_key = palloc0(len + 1);
+	server_key = palloc0_array(char, len + 1);
 	encoded_len = pg_b64_encode(MyProcPort->scram_ServerKey,
 								sizeof(MyProcPort->scram_ServerKey),
 								server_key, len);
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index 33a37d832ce..7d9dc3baf74 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -1206,8 +1206,8 @@ file_acquire_sample_rows(Relation onerel, int elevel,
 	Assert(targrows > 0);
 
 	tupDesc = RelationGetDescr(onerel);
-	values = (Datum *) palloc(tupDesc->natts * sizeof(Datum));
-	nulls = (bool *) palloc(tupDesc->natts * sizeof(bool));
+	values = palloc_array(Datum, tupDesc->natts);
+	nulls = palloc_array(bool, tupDesc->natts);
 
 	/* Fetch options of foreign table */
 	fileGetOptions(RelationGetRelid(onerel), &filename, &is_program, &options);
diff --git a/contrib/fuzzystrmatch/dmetaphone.c b/contrib/fuzzystrmatch/dmetaphone.c
index 3bd03ba1e5e..fc362dc839b 100644
--- a/contrib/fuzzystrmatch/dmetaphone.c
+++ b/contrib/fuzzystrmatch/dmetaphone.c
@@ -186,7 +186,7 @@ dmetaphone_alt(PG_FUNCTION_ARGS)
 /* all memory handling is done with these macros */
 
 #define META_MALLOC(v,n,t) \
-		  (v = (t*)palloc(((n)*sizeof(t))))
+		  (v = palloc_array(t, (n)))
 
 #define META_REALLOC(v,n,t) \
 					  (v = (t*)repalloc((v),((n)*sizeof(t))))
diff --git a/contrib/fuzzystrmatch/fuzzystrmatch.c b/contrib/fuzzystrmatch/fuzzystrmatch.c
index e527b1048b5..5ee8961228f 100644
--- a/contrib/fuzzystrmatch/fuzzystrmatch.c
+++ b/contrib/fuzzystrmatch/fuzzystrmatch.c
@@ -379,11 +379,11 @@ _metaphone(char *word,			/* IN */
 	/*-- Allocate memory for our phoned_phrase --*/
 	if (max_phonemes == 0)
 	{							/* Assume largest possible */
-		*phoned_word = palloc(sizeof(char) * strlen(word) + 1);
+		*phoned_word = palloc_array(char, strlen(word) + 1);
 	}
 	else
 	{
-		*phoned_word = palloc(sizeof(char) * max_phonemes + 1);
+		*phoned_word = palloc_array(char, max_phonemes + 1);
 	}
 
 	/*-- The first phoneme has to be processed specially. --*/
diff --git a/contrib/hstore/hstore_gin.c b/contrib/hstore/hstore_gin.c
index 1365539f95f..a5fdc676c96 100644
--- a/contrib/hstore/hstore_gin.c
+++ b/contrib/hstore/hstore_gin.c
@@ -53,7 +53,7 @@ gin_extract_hstore(PG_FUNCTION_ARGS)
 
 	*nentries = 2 * count;
 	if (count)
-		entries = (Datum *) palloc(sizeof(Datum) * 2 * count);
+		entries = palloc_array(Datum, 2 * count);
 
 	for (i = 0; i < count; ++i)
 	{
@@ -120,7 +120,7 @@ gin_extract_hstore_query(PG_FUNCTION_ARGS)
 
 		deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count);
 
-		entries = (Datum *) palloc(sizeof(Datum) * key_count);
+		entries = palloc_array(Datum, key_count);
 
 		for (i = 0, j = 0; i < key_count; ++i)
 		{
diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c
index 9b72efb8674..ef19b522b8e 100644
--- a/contrib/hstore/hstore_io.c
+++ b/contrib/hstore/hstore_io.c
@@ -523,7 +523,7 @@ hstore_recv(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 				 errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
 						pcount, (int) (MaxAllocSize / sizeof(Pairs)))));
-	pairs = palloc(pcount * sizeof(Pairs));
+	pairs = palloc_array(Pairs, pcount);
 
 	for (i = 0; i < pcount; ++i)
 	{
@@ -674,7 +674,7 @@ hstore_from_arrays(PG_FUNCTION_ARGS)
 		Assert(key_count == value_count);
 	}
 
-	pairs = palloc(key_count * sizeof(Pairs));
+	pairs = palloc_array(Pairs, key_count);
 
 	for (i = 0; i < key_count; ++i)
 	{
@@ -768,7 +768,7 @@ hstore_from_array(PG_FUNCTION_ARGS)
 				 errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
 						count, (int) (MaxAllocSize / sizeof(Pairs)))));
 
-	pairs = palloc(count * sizeof(Pairs));
+	pairs = palloc_array(Pairs, count);
 
 	for (i = 0; i < count; ++i)
 	{
@@ -909,7 +909,7 @@ hstore_from_record(PG_FUNCTION_ARGS)
 	}
 
 	Assert(ncolumns <= MaxTupleAttributeNumber);	/* thus, no overflow */
-	pairs = palloc(ncolumns * sizeof(Pairs));
+	pairs = palloc_array(Pairs, ncolumns);
 
 	if (rec)
 	{
@@ -919,8 +919,8 @@ hstore_from_record(PG_FUNCTION_ARGS)
 		tuple.t_tableOid = InvalidOid;
 		tuple.t_data = rec;
 
-		values = (Datum *) palloc(ncolumns * sizeof(Datum));
-		nulls = (bool *) palloc(ncolumns * sizeof(bool));
+		values = palloc_array(Datum, ncolumns);
+		nulls = palloc_array(bool, ncolumns);
 
 		/* Break down the tuple into fields */
 		heap_deform_tuple(&tuple, tupdesc, values, nulls);
@@ -1102,8 +1102,8 @@ hstore_populate_record(PG_FUNCTION_ARGS)
 		my_extra->ncolumns = ncolumns;
 	}
 
-	values = (Datum *) palloc(ncolumns * sizeof(Datum));
-	nulls = (bool *) palloc(ncolumns * sizeof(bool));
+	values = palloc_array(Datum, ncolumns);
+	nulls = palloc_array(bool, ncolumns);
 
 	if (rec)
 	{
diff --git a/contrib/hstore/hstore_op.c b/contrib/hstore/hstore_op.c
index bcba75f9258..cab59700c0d 100644
--- a/contrib/hstore/hstore_op.c
+++ b/contrib/hstore/hstore_op.c
@@ -101,7 +101,7 @@ hstoreArrayToPairs(ArrayType *a, int *npairs)
 				 errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
 						key_count, (int) (MaxAllocSize / sizeof(Pairs)))));
 
-	key_pairs = palloc(sizeof(Pairs) * key_count);
+	key_pairs = palloc_array(Pairs, key_count);
 
 	for (i = 0, j = 0; i < key_count; i++)
 	{
@@ -588,8 +588,8 @@ hstore_slice_to_array(PG_FUNCTION_ARGS)
 		PG_RETURN_POINTER(aout);
 	}
 
-	out_datums = palloc(sizeof(Datum) * key_count);
-	out_nulls = palloc(sizeof(bool) * key_count);
+	out_datums = palloc_array(Datum, key_count);
+	out_nulls = palloc_array(bool, key_count);
 
 	for (i = 0; i < key_count; ++i)
 	{
@@ -649,7 +649,7 @@ hstore_slice_to_hstore(PG_FUNCTION_ARGS)
 	}
 
 	/* hstoreArrayToPairs() checked overflow */
-	out_pairs = palloc(sizeof(Pairs) * nkeys);
+	out_pairs = palloc_array(Pairs, nkeys);
 	bufsiz = 0;
 
 	/*
@@ -705,7 +705,7 @@ hstore_akeys(PG_FUNCTION_ARGS)
 		PG_RETURN_POINTER(a);
 	}
 
-	d = (Datum *) palloc(sizeof(Datum) * count);
+	d = palloc_array(Datum, count);
 
 	for (i = 0; i < count; ++i)
 	{
@@ -741,8 +741,8 @@ hstore_avals(PG_FUNCTION_ARGS)
 		PG_RETURN_POINTER(a);
 	}
 
-	d = (Datum *) palloc(sizeof(Datum) * count);
-	nulls = (bool *) palloc(sizeof(bool) * count);
+	d = palloc_array(Datum, count);
+	nulls = palloc_array(bool, count);
 
 	for (i = 0; i < count; ++i)
 	{
@@ -786,8 +786,8 @@ hstore_to_array_internal(HStore *hs, int ndims)
 		return construct_empty_array(TEXTOID);
 
 	out_size[0] = count * 2 / ndims;
-	out_datums = palloc(sizeof(Datum) * count * 2);
-	out_nulls = palloc(sizeof(bool) * count * 2);
+	out_datums = palloc_array(Datum, count * 2);
+	out_nulls = palloc_array(bool, count * 2);
 
 	for (i = 0; i < count; ++i)
 	{
diff --git a/contrib/ltree/lquery_op.c b/contrib/ltree/lquery_op.c
index e6a1969c3d3..7bde4cbbbac 100644
--- a/contrib/ltree/lquery_op.c
+++ b/contrib/ltree/lquery_op.c
@@ -104,7 +104,7 @@ ltree_label_match(const char *pred, size_t pred_len, const char *label,
 	if (!locale)
 		locale = pg_database_locale();
 
-	fpred = palloc(fpred_len + 1);
+	fpred = palloc_array(char, fpred_len + 1);
 	len = pg_strfold(fpred, fpred_len + 1, pred, pred_len, locale);
 	if (len > fpred_len)
 	{
@@ -116,7 +116,7 @@ ltree_label_match(const char *pred, size_t pred_len, const char *label,
 	Assert(len <= fpred_len);
 	fpred_len = len;
 
-	flabel = palloc(flabel_len + 1);
+	flabel = palloc_array(char, flabel_len + 1);
 	len = pg_strfold(flabel, flabel_len + 1, label, label_len, locale);
 	if (len > flabel_len)
 	{
diff --git a/contrib/ltree/ltree_io.c b/contrib/ltree/ltree_io.c
index 88d2ef0c917..fe08da8fc24 100644
--- a/contrib/ltree/ltree_io.c
+++ b/contrib/ltree/ltree_io.c
@@ -149,7 +149,7 @@ deparse_ltree(const ltree *in)
 	int			i;
 	ltree_level *curlevel;
 
-	ptr = buf = (char *) palloc(VARSIZE(in));
+	ptr = buf = palloc_array(char, VARSIZE(in));
 	curlevel = LTREE_FIRST(in);
 	for (i = 0; i < in->numlevel; i++)
 	{
@@ -664,7 +664,7 @@ deparse_lquery(const lquery *in)
 		curqlevel = LQL_NEXT(curqlevel);
 	}
 
-	ptr = buf = (char *) palloc(totallen);
+	ptr = buf = palloc_array(char, totallen);
 	curqlevel = LQUERY_FIRST(in);
 	for (i = 0; i < in->numlevel; i++)
 	{
diff --git a/contrib/ltree/ltxtquery_io.c b/contrib/ltree/ltxtquery_io.c
index b1354b9227c..f1ec8d21954 100644
--- a/contrib/ltree/ltxtquery_io.c
+++ b/contrib/ltree/ltxtquery_io.c
@@ -387,7 +387,7 @@ queryin(char *buf, struct Node *escontext)
 	/* init list of operand */
 	state.sumlen = 0;
 	state.lenop = 64;
-	state.curop = state.op = (char *) palloc(state.lenop);
+	state.curop = state.op = palloc_array(char, state.lenop);
 	*(state.curop) = '\0';
 
 	/* parse query & make polish notation (postfix, but in reverse order) */
diff --git a/contrib/pageinspect/btreefuncs.c b/contrib/pageinspect/btreefuncs.c
index 3381e7cc2a7..c3932ffc24f 100644
--- a/contrib/pageinspect/btreefuncs.c
+++ b/contrib/pageinspect/btreefuncs.c
@@ -547,7 +547,7 @@ bt_page_print_tuples(ua_page_items *uargs)
 	if (dlen < 0 || dlen > INDEX_SIZE_MASK)
 		elog(ERROR, "invalid tuple length %d for tuple at offset number %u",
 			 dlen, offset);
-	dump = palloc0(dlen * 3 + 1);
+	dump = palloc0_array(char, dlen * 3 + 1);
 	datacstring = dump;
 	for (off = 0; off < dlen; off++)
 	{
@@ -597,7 +597,7 @@ bt_page_print_tuples(ua_page_items *uargs)
 
 		tids = BTreeTupleGetPosting(itup);
 		nposting = BTreeTupleGetNPosting(itup);
-		tids_datum = (Datum *) palloc(nposting * sizeof(Datum));
+		tids_datum = palloc_array(Datum, nposting);
 		for (int i = 0; i < nposting; i++)
 			tids_datum[i] = ItemPointerGetDatum(&tids[i]);
 		values[j++] = PointerGetDatum(construct_array_builtin(tids_datum, nposting, TIDOID));
diff --git a/contrib/pageinspect/ginfuncs.c b/contrib/pageinspect/ginfuncs.c
index e4461db7f0a..058ad52b671 100644
--- a/contrib/pageinspect/ginfuncs.c
+++ b/contrib/pageinspect/ginfuncs.c
@@ -262,7 +262,7 @@ gin_leafpage_items(PG_FUNCTION_ARGS)
 
 		/* build an array of decoded item pointers */
 		tids = ginPostingListDecode(cur, &ndecoded);
-		tids_datum = (Datum *) palloc(ndecoded * sizeof(Datum));
+		tids_datum = palloc_array(Datum, ndecoded);
 		for (i = 0; i < ndecoded; i++)
 			tids_datum[i] = ItemPointerGetDatum(&tids[i]);
 		values[2] = PointerGetDatum(construct_array_builtin(tids_datum, ndecoded, TIDOID));
diff --git a/contrib/pg_logicalinspect/pg_logicalinspect.c b/contrib/pg_logicalinspect/pg_logicalinspect.c
index 20b63ed4b8e..ee6c141e5bc 100644
--- a/contrib/pg_logicalinspect/pg_logicalinspect.c
+++ b/contrib/pg_logicalinspect/pg_logicalinspect.c
@@ -168,7 +168,7 @@ pg_get_logical_snapshot_info(PG_FUNCTION_ARGS)
 	{
 		Datum	   *arrayelems;
 
-		arrayelems = (Datum *) palloc(ondisk.builder.committed.xcnt * sizeof(Datum));
+		arrayelems = palloc_array(Datum, ondisk.builder.committed.xcnt);
 
 		for (size_t j = 0; j < ondisk.builder.committed.xcnt; j++)
 			arrayelems[j] = TransactionIdGetDatum(ondisk.builder.committed.xip[j]);
@@ -185,7 +185,7 @@ pg_get_logical_snapshot_info(PG_FUNCTION_ARGS)
 	{
 		Datum	   *arrayelems;
 
-		arrayelems = (Datum *) palloc(ondisk.builder.catchange.xcnt * sizeof(Datum));
+		arrayelems = palloc_array(Datum, ondisk.builder.catchange.xcnt);
 
 		for (size_t j = 0; j < ondisk.builder.catchange.xcnt; j++)
 			arrayelems[j] = TransactionIdGetDatum(ondisk.builder.catchange.xip[j]);
diff --git a/contrib/pg_stash_advice/stashpersist.c b/contrib/pg_stash_advice/stashpersist.c
index 5bdf4bddaae..ee53caafc7e 100644
--- a/contrib/pg_stash_advice/stashpersist.c
+++ b/contrib/pg_stash_advice/stashpersist.c
@@ -319,7 +319,7 @@ pgsa_read_from_disk(void)
 
 	/* Initial memory allocations. */
 	saved_stashes = pgsa_saved_stash_table_create(tmpcxt, 64, NULL);
-	entries = palloc(max_entries * sizeof(pgsa_saved_entry));
+	entries = palloc_array(pgsa_saved_entry, max_entries);
 
 	/*
 	 * For memory and CPU efficiency, we parse the file in place. The end of
diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index 92315627916..d981baca741 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -608,7 +608,7 @@ pgss_shmem_init(void *arg)
 	}
 
 	buffer_size = 2048;
-	buffer = (char *) palloc(buffer_size);
+	buffer = palloc_array(char, buffer_size);
 
 	if (fread(&header, sizeof(uint32), 1, file) != 1 ||
 		fread(&pgver, sizeof(uint32), 1, file) != 1 ||
@@ -2159,7 +2159,7 @@ entry_dealloc(void)
 	 * cur_median_usage includes the entries we're about to zap.
 	 */
 
-	entries = palloc(hash_get_num_entries(pgss_hash) * sizeof(pgssEntry *));
+	entries = palloc_array(pgssEntry *, hash_get_num_entries(pgss_hash));
 
 	i = 0;
 	tottextlen = 0;
diff --git a/contrib/pg_trgm/trgm_gist.c b/contrib/pg_trgm/trgm_gist.c
index bfe2b10fae5..4f468e15b59 100644
--- a/contrib/pg_trgm/trgm_gist.c
+++ b/contrib/pg_trgm/trgm_gist.c
@@ -424,7 +424,7 @@ gtrgm_consistent(PG_FUNCTION_ARGS)
 					 * So we can apply trigramsMatchGraph despite uncertainty,
 					 * and that usefully improves the quality of the search.
 					 */
-					check = (bool *) palloc(len * sizeof(bool));
+					check = palloc_array(bool, len);
 					for (k = 0; k < len; k++)
 					{
 						CPTRGM(&tmp, ptr + k);
diff --git a/contrib/pg_trgm/trgm_op.c b/contrib/pg_trgm/trgm_op.c
index 22bcc3c3361..89e6d679f21 100644
--- a/contrib/pg_trgm/trgm_op.c
+++ b/contrib/pg_trgm/trgm_op.c
@@ -524,7 +524,7 @@ generate_trgm_only(growable_trgm_array *dst, char *str, int slen, TrgmBound **bo
 	 * original, we'll grow the buffer.
 	 */
 	buflen = (size_t) slen + 4;
-	buf = (char *) palloc(buflen);
+	buf = palloc_array(char, buflen);
 	if (LPADDING > 0)
 	{
 		*buf = ' ';
@@ -550,7 +550,7 @@ generate_trgm_only(growable_trgm_array *dst, char *str, int slen, TrgmBound **bo
 			{
 				pfree(buf);
 				buflen = (size_t) bytelen + 4;
-				buf = (char *) palloc(buflen);
+				buf = palloc_array(char, buflen);
 				if (LPADDING > 0)
 				{
 					*buf = ' ';
diff --git a/contrib/pg_trgm/trgm_regexp.c b/contrib/pg_trgm/trgm_regexp.c
index b4eaeec6090..b3eca178c5a 100644
--- a/contrib/pg_trgm/trgm_regexp.c
+++ b/contrib/pg_trgm/trgm_regexp.c
@@ -728,7 +728,7 @@ RE_compile(regex_t *regex, text *text_re, int cflags, Oid collation)
 	char		errMsg[100];
 
 	/* Convert pattern string to wide characters */
-	pattern = (pg_wchar *) palloc((text_re_len + 1) * sizeof(pg_wchar));
+	pattern = palloc_array(pg_wchar, text_re_len + 1);
 	pattern_len = pg_mb2wchar_with_len(text_re_val,
 									   pattern,
 									   text_re_len);
@@ -768,8 +768,7 @@ getColorInfo(regex_t *regex, TrgmNFA *trgmNFA)
 	int			i;
 
 	trgmNFA->ncolors = colorsCount;
-	trgmNFA->colorInfo = (TrgmColorInfo *)
-		palloc0(colorsCount * sizeof(TrgmColorInfo));
+	trgmNFA->colorInfo = palloc0_array(TrgmColorInfo, colorsCount);
 
 	/*
 	 * Loop over colors, filling TrgmColorInfo about each.  Note we include
diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c
index dfab0b64cf5..85f6463e1f1 100644
--- a/contrib/pg_visibility/pg_visibility.c
+++ b/contrib/pg_visibility/pg_visibility.c
@@ -725,7 +725,7 @@ collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen)
 	items = palloc0_object(corrupt_items);
 	items->next = 0;
 	items->count = 64;
-	items->tids = palloc(items->count * sizeof(ItemPointerData));
+	items->tids = palloc_array(ItemPointerData, items->count);
 
 	p.current_blocknum = 0;
 	p.last_exclusive = RelationGetNumberOfBlocks(rel);
diff --git a/contrib/pgcrypto/mbuf.c b/contrib/pgcrypto/mbuf.c
index 6a23ad99706..ce9bca74c7d 100644
--- a/contrib/pgcrypto/mbuf.c
+++ b/contrib/pgcrypto/mbuf.c
@@ -116,7 +116,7 @@ mbuf_create(int len)
 		len = 8192;
 
 	mbuf = palloc_object(MBuf);
-	mbuf->data = palloc(len);
+	mbuf->data = palloc_array(uint8, len);
 	mbuf->buf_end = mbuf->data + len;
 	mbuf->data_end = mbuf->data;
 	mbuf->read_pos = mbuf->data;
diff --git a/contrib/pgcrypto/pgcrypto.c b/contrib/pgcrypto/pgcrypto.c
index 9ecbbd2e2f8..eb198adb393 100644
--- a/contrib/pgcrypto/pgcrypto.c
+++ b/contrib/pgcrypto/pgcrypto.c
@@ -223,7 +223,7 @@ pg_crypt(PG_FUNCTION_ARGS)
 	buf0 = text_to_cstring(arg0);
 	buf1 = text_to_cstring(arg1);
 
-	resbuf = palloc0(PX_MAX_CRYPT);
+	resbuf = palloc0_array(char, PX_MAX_CRYPT);
 
 	cres = px_crypt(buf0, buf1, resbuf, PX_MAX_CRYPT);
 
diff --git a/contrib/pgcrypto/pgp-armor.c b/contrib/pgcrypto/pgp-armor.c
index bfc90af063d..3af551bf3b8 100644
--- a/contrib/pgcrypto/pgp-armor.c
+++ b/contrib/pgcrypto/pgp-armor.c
@@ -436,13 +436,13 @@ pgp_extract_armor_headers(const uint8 *src, unsigned len,
 	 * headers. The returned key/value pointers will point inside the buffer.
 	 */
 	armor_len = base64_start - armor_start;
-	buf = palloc(armor_len + 1);
+	buf = palloc_array(char, armor_len + 1);
 	memcpy(buf, armor_start, armor_len);
 	buf[armor_len] = '\0';
 
 	/* Allocate return arrays */
-	*keys = (char **) palloc(hdrlines * sizeof(char *));
-	*values = (char **) palloc(hdrlines * sizeof(char *));
+	*keys = palloc_array(char *, hdrlines);
+	*values = palloc_array(char *, hdrlines);
 
 	/*
 	 * Split the header lines at newlines and ": " separators, and collect
diff --git a/contrib/pgcrypto/px-hmac.c b/contrib/pgcrypto/px-hmac.c
index 68e5cff6d6a..5b9ffb90c05 100644
--- a/contrib/pgcrypto/px-hmac.c
+++ b/contrib/pgcrypto/px-hmac.c
@@ -57,7 +57,7 @@ hmac_init(PX_HMAC *h, const uint8 *key, unsigned klen)
 	PX_MD	   *md = h->md;
 
 	bs = px_md_block_size(md);
-	keybuf = palloc0(bs);
+	keybuf = palloc0_array(uint8, bs);
 
 	if (klen > bs)
 	{
diff --git a/contrib/pgcrypto/px.c b/contrib/pgcrypto/px.c
index 32f62f3fc1b..c4b0ae51bde 100644
--- a/contrib/pgcrypto/px.c
+++ b/contrib/pgcrypto/px.c
@@ -194,7 +194,7 @@ combo_init(PX_Combo *cx, const uint8 *key, unsigned klen,
 	ivs = px_cipher_iv_size(c);
 	if (ivs > 0)
 	{
-		ivbuf = palloc0(ivs);
+		ivbuf = palloc0_array(uint8, ivs);
 		if (ivlen > ivs)
 			memcpy(ivbuf, iv, ivs);
 		else if (ivlen > 0)
@@ -203,7 +203,7 @@ combo_init(PX_Combo *cx, const uint8 *key, unsigned klen,
 
 	if (klen > ks)
 		klen = ks;
-	keybuf = palloc0(ks);
+	keybuf = palloc0_array(uint8, ks);
 	memcpy(keybuf, key, klen);
 
 	err = px_cipher_init(c, keybuf, klen, ivbuf);
diff --git a/contrib/pgrowlocks/pgrowlocks.c b/contrib/pgrowlocks/pgrowlocks.c
index d164c4c03ad..7304ca44a0a 100644
--- a/contrib/pgrowlocks/pgrowlocks.c
+++ b/contrib/pgrowlocks/pgrowlocks.c
@@ -120,7 +120,7 @@ pgrowlocks(PG_FUNCTION_ARGS)
 
 	attinmeta = TupleDescGetAttInMetadata(rsinfo->setDesc);
 
-	values = (char **) palloc(rsinfo->setDesc->natts * sizeof(char *));
+	values = palloc_array(char *, rsinfo->setDesc->natts);
 
 	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
@@ -145,7 +145,7 @@ pgrowlocks(PG_FUNCTION_ARGS)
 			values[Atnum_tid] = DatumGetCString(DirectFunctionCall1(tidout,
 																	PointerGetDatum(&tuple->t_self)));
 
-			values[Atnum_xmax] = palloc(NCHARS * sizeof(char));
+			values[Atnum_xmax] = palloc_array(char, NCHARS);
 			snprintf(values[Atnum_xmax], NCHARS, "%u", xmax);
 			if (infomask & HEAP_XMAX_IS_MULTI)
 			{
@@ -227,10 +227,10 @@ pgrowlocks(PG_FUNCTION_ARGS)
 			{
 				values[Atnum_ismulti] = pstrdup("false");
 
-				values[Atnum_xids] = palloc(NCHARS * sizeof(char));
+				values[Atnum_xids] = palloc_array(char, NCHARS);
 				snprintf(values[Atnum_xids], NCHARS, "{%u}", xmax);
 
-				values[Atnum_modes] = palloc(NCHARS);
+				values[Atnum_modes] = palloc_array(char, NCHARS);
 				if (infomask & HEAP_XMAX_LOCK_ONLY)
 				{
 					if (HEAP_XMAX_IS_SHR_LOCKED(infomask))
@@ -257,7 +257,7 @@ pgrowlocks(PG_FUNCTION_ARGS)
 						snprintf(values[Atnum_modes], NCHARS, "{No Key Update}");
 				}
 
-				values[Atnum_pids] = palloc(NCHARS * sizeof(char));
+				values[Atnum_pids] = palloc_array(char, NCHARS);
 				snprintf(values[Atnum_pids], NCHARS, "{%d}",
 						 BackendXidGetPid(xmax));
 			}
diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c
index 094eac2f343..6a2b528ddcc 100644
--- a/contrib/postgres_fdw/connection.c
+++ b/contrib/postgres_fdw/connection.c
@@ -507,8 +507,8 @@ construct_connection_params(ForeignServer *server, UserMapping *user,
 	 * required scram pass-through options.
 	 */
 	n = list_length(server->options) + list_length(user->options) + 4 + 3;
-	keywords = (const char **) palloc(n * sizeof(char *));
-	values = (const char **) palloc(n * sizeof(char *));
+	keywords = palloc_array(const char *, n);
+	values = palloc_array(const char *, n);
 
 	n = 0;
 	n += ExtractConnectionOptions(server->options,
@@ -585,7 +585,7 @@ construct_connection_params(ForeignServer *server, UserMapping *user,
 		keywords[n] = "scram_client_key";
 		len = pg_b64_enc_len(sizeof(MyProcPort->scram_ClientKey));
 		/* don't forget the zero-terminator */
-		values[n] = palloc0(len + 1);
+		values[n] = palloc0_array(char, len + 1);
 		encoded_len = pg_b64_encode(MyProcPort->scram_ClientKey,
 									sizeof(MyProcPort->scram_ClientKey),
 									(char *) values[n], len);
@@ -596,7 +596,7 @@ construct_connection_params(ForeignServer *server, UserMapping *user,
 		keywords[n] = "scram_server_key";
 		len = pg_b64_enc_len(sizeof(MyProcPort->scram_ServerKey));
 		/* don't forget the zero-terminator */
-		values[n] = palloc0(len + 1);
+		values[n] = palloc0_array(char, len + 1);
 		encoded_len = pg_b64_encode(MyProcPort->scram_ServerKey,
 									sizeof(MyProcPort->scram_ServerKey),
 									(char *) values[n], len);
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index b9739610131..11ec90a5982 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -3933,7 +3933,7 @@ fetch_more_data(ForeignScanState *node)
 
 	/* Convert the data into HeapTuples */
 	numrows = PQntuples(res);
-	fsstate->tuples = (HeapTuple *) palloc0(numrows * sizeof(HeapTuple));
+	fsstate->tuples = palloc0_array(HeapTuple, numrows);
 	fsstate->num_tuples = numrows;
 	fsstate->next_tuple = 0;
 
@@ -4345,7 +4345,7 @@ convert_prep_stmt_params(PgFdwModifyState *fmstate,
 
 	oldcontext = MemoryContextSwitchTo(fmstate->temp_cxt);
 
-	p_values = (const char **) palloc(sizeof(char *) * fmstate->p_nums * numSlots);
+	p_values = palloc_array(const char *, fmstate->p_nums * numSlots);
 
 	/* ctid is provided only for UPDATE/DELETE, which don't allow batching */
 	Assert(!(tupleid != NULL && numSlots > 1));
@@ -4738,8 +4738,7 @@ init_returning_filter(PgFdwDirectModifyState *dmstate,
 	 *
 	 * Also get the indexes of the entries for ctid and oid if any.
 	 */
-	dmstate->attnoMap = (AttrNumber *)
-		palloc0(resultTupType->natts * sizeof(AttrNumber));
+	dmstate->attnoMap = palloc0_array(AttrNumber, resultTupType->natts);
 
 	dmstate->ctidAttno = dmstate->oidAttno = 0;
 
@@ -4928,7 +4927,7 @@ prepare_query_params(PlanState *node,
 	*param_exprs = ExecInitExprList(fdw_exprs, node);
 
 	/* Allocate buffer for text form of query parameters. */
-	*param_values = (const char **) palloc0(numParams * sizeof(char *));
+	*param_values = palloc0_array(const char *, numParams);
 }
 
 /*
@@ -8403,8 +8402,8 @@ make_tuple_from_result_row(PGresult *res,
 		tupdesc = fsstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
 	}
 
-	values = (Datum *) palloc0(tupdesc->natts * sizeof(Datum));
-	nulls = (bool *) palloc(tupdesc->natts * sizeof(bool));
+	values = palloc0_array(Datum, tupdesc->natts);
+	nulls = palloc_array(bool, tupdesc->natts);
 	/* Initialize to nulls for any columns not present in result */
 	memset(nulls, true, tupdesc->natts * sizeof(bool));
 
diff --git a/contrib/seg/seg.c b/contrib/seg/seg.c
index c7b374825f8..cf0875a6bb9 100644
--- a/contrib/seg/seg.c
+++ b/contrib/seg/seg.c
@@ -127,7 +127,7 @@ seg_out(PG_FUNCTION_ARGS)
 	char	   *result;
 	char	   *p;
 
-	p = result = (char *) palloc(40);
+	p = result = palloc_array(char, 40);
 
 	if (seg->l_ext == '>' || seg->l_ext == '<' || seg->l_ext == '~')
 		p += sprintf(p, "%c", seg->l_ext);
@@ -345,8 +345,7 @@ gseg_picksplit(PG_FUNCTION_ARGS)
 	/*
 	 * Prepare the auxiliary array and sort it.
 	 */
-	sort_items = (gseg_picksplit_item *)
-		palloc(maxoff * sizeof(gseg_picksplit_item));
+	sort_items = palloc_array(gseg_picksplit_item, maxoff);
 	for (i = 1; i <= maxoff; i++)
 	{
 		seg = DatumGetSegP(entryvec->vector[i].key);
@@ -361,8 +360,8 @@ gseg_picksplit(PG_FUNCTION_ARGS)
 	/* sort items below "firstright" will go into the left side */
 	firstright = maxoff / 2;
 
-	v->spl_left = (OffsetNumber *) palloc(maxoff * sizeof(OffsetNumber));
-	v->spl_right = (OffsetNumber *) palloc(maxoff * sizeof(OffsetNumber));
+	v->spl_left = palloc_array(OffsetNumber, maxoff);
+	v->spl_right = palloc_array(OffsetNumber, maxoff);
 	left = v->spl_left;
 	v->spl_nleft = 0;
 	right = v->spl_right;
diff --git a/contrib/tablefunc/tablefunc.c b/contrib/tablefunc/tablefunc.c
index 31f70b7bc10..5e5cc6a71e0 100644
--- a/contrib/tablefunc/tablefunc.c
+++ b/contrib/tablefunc/tablefunc.c
@@ -487,7 +487,7 @@ crosstab(PG_FUNCTION_ARGS)
 		char	  **values;
 
 		/* allocate and zero space */
-		values = (char **) palloc0((1 + num_categories) * sizeof(char *));
+		values = palloc0_array(char *, 1 + num_categories);
 
 		/*
 		 * now loop through the sql results and assign each value in sequence
@@ -864,7 +864,7 @@ get_crosstab_tuplestore(char *sql,
 							   result_ncols, tupdesc->natts)));
 
 		/* allocate space and make sure it's clear */
-		values = (char **) palloc0(result_ncols * sizeof(char *));
+		values = palloc0_array(char *, result_ncols);
 
 		for (i = 0; i < proc; i++)
 		{
@@ -1247,9 +1247,9 @@ build_tuplestore_recursively(char *key_fld,
 	}
 
 	if (show_branch)
-		values = (char **) palloc((CONNECTBY_NCOLS + serial_column) * sizeof(char *));
+		values = palloc_array(char *, CONNECTBY_NCOLS + serial_column);
 	else
-		values = (char **) palloc((CONNECTBY_NCOLS_NOBRANCH + serial_column) * sizeof(char *));
+		values = palloc_array(char *, CONNECTBY_NCOLS_NOBRANCH + serial_column);
 
 	/* First time through, do a little setup */
 	if (level == 0)
diff --git a/contrib/unaccent/unaccent.c b/contrib/unaccent/unaccent.c
index 69b173e4498..0e6612ea649 100644
--- a/contrib/unaccent/unaccent.c
+++ b/contrib/unaccent/unaccent.c
@@ -75,7 +75,7 @@ placeChar(TrieChar *node, const unsigned char *str, int lenstr,
 		else
 		{
 			curnode->replacelen = replacelen;
-			curnode->replaceTo = (char *) palloc(replacelen);
+			curnode->replaceTo = palloc_array(char, replacelen);
 			memcpy(curnode->replaceTo, replaceTo, replacelen);
 		}
 	}
diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 391e39827ce..4cb924541e3 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -700,8 +700,8 @@ xpath_table(PG_FUNCTION_ARGS)
 
 	attinmeta = TupleDescGetAttInMetadata(rsinfo->setDesc);
 
-	values = (char **) palloc0(rsinfo->setDesc->natts * sizeof(char *));
-	xpaths = (xmlChar **) palloc(rsinfo->setDesc->natts * sizeof(xmlChar *));
+	values = palloc0_array(char *, rsinfo->setDesc->natts);
+	xpaths = palloc_array(xmlChar *, rsinfo->setDesc->natts);
 
 	/*
 	 * Split XPaths. xpathset is a writable CString.
diff --git a/contrib/xml2/xslt_proc.c b/contrib/xml2/xslt_proc.c
index c42469cfaa3..78b60b7dfea 100644
--- a/contrib/xml2/xslt_proc.c
+++ b/contrib/xml2/xslt_proc.c
@@ -228,7 +228,7 @@ parse_params(text *paramstr)
 	pstr = text_to_cstring(paramstr);
 
 	max_params = 20;			/* must be even! */
-	params = (const char **) palloc((max_params + 1) * sizeof(char *));
+	params = palloc_array(const char *, max_params + 1);
 	nparams = 0;
 
 	pos = pstr;
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index 2b8a11e7ad0..050e1e50bec 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -3454,10 +3454,10 @@ retcomposite(PG_FUNCTION_ARGS)
          * This should be an array of C strings which will
          * be processed later by the type input functions.
          */
-        values = (char **) palloc(3 * sizeof(char *));
-        values[0] = (char *) palloc(16 * sizeof(char));
-        values[1] = (char *) palloc(16 * sizeof(char));
-        values[2] = (char *) palloc(16 * sizeof(char));
+        values = palloc_array(char *, 3);
+        values[0] = palloc_array(char, 16);
+        values[1] = palloc_array(char, 16);
+        values[2] = palloc_array(char, 16);
 
         snprintf(values[0], 16, "%d", 1 * PG_GETARG_INT32(1));
         snprintf(values[1], 16, "%d", 2 * PG_GETARG_INT32(1));
diff --git a/src/backend/access/brin/brin_minmax_multi.c b/src/backend/access/brin/brin_minmax_multi.c
index 207ae336091..1a6056a6b47 100644
--- a/src/backend/access/brin/brin_minmax_multi.c
+++ b/src/backend/access/brin/brin_minmax_multi.c
@@ -1390,7 +1390,7 @@ build_expanded_ranges(FmgrInfo *cmp, Oid colloid, Ranges *ranges,
 	/* both ranges and points are expanded into a separate element */
 	neranges = ranges->nranges + ranges->nvalues;
 
-	eranges = (ExpandedRange *) palloc0(neranges * sizeof(ExpandedRange));
+	eranges = palloc0_array(ExpandedRange, neranges);
 
 	/* fill the expanded ranges */
 	fill_expanded_ranges(eranges, neranges, ranges);
@@ -2783,7 +2783,7 @@ brin_minmax_multi_union(PG_FUNCTION_ARGS)
 	oldctx = MemoryContextSwitchTo(ctx);
 
 	/* allocate and fill */
-	eranges = (ExpandedRange *) palloc0(neranges * sizeof(ExpandedRange));
+	eranges = palloc0_array(ExpandedRange, neranges);
 
 	/* fill the expanded ranges with entries for the first range */
 	fill_expanded_ranges(eranges, ranges_a->nranges + ranges_a->nvalues,
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index f30346469ed..0eb8f17b744 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -1438,7 +1438,7 @@ heap_form_minimal_tuple(TupleDesc tupleDescriptor,
 	/*
 	 * Allocate and zero the space needed.
 	 */
-	mem = palloc0(len + extra);
+	mem = palloc0_array(char, len + extra);
 	tuple = (MinimalTuple) (mem + extra);
 
 	/*
diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c
index 616bdafd395..06d56cf2f20 100644
--- a/src/backend/access/common/printtup.c
+++ b/src/backend/access/common/printtup.c
@@ -263,8 +263,7 @@ printtup_prepare_info(DR_printtup *myState, TupleDesc typeinfo, int numAttrs)
 	if (numAttrs <= 0)
 		return;
 
-	myState->myinfo = (PrinttupAttrInfo *)
-		palloc0(numAttrs * sizeof(PrinttupAttrInfo));
+	myState->myinfo = palloc0_array(PrinttupAttrInfo, numAttrs);
 
 	for (i = 0; i < numAttrs; i++)
 	{
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 3e832c3797e..aacd3e8534b 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -768,7 +768,7 @@ add_reloption(relopt_gen *newoption)
 		if (max_custom_options == 0)
 		{
 			max_custom_options = 8;
-			custom_options = palloc(max_custom_options * sizeof(relopt_gen *));
+			custom_options = palloc_array(relopt_gen *, max_custom_options);
 		}
 		else
 		{
@@ -1634,7 +1634,7 @@ parseRelOptions(Datum options, bool validate, relopt_kind kind,
 
 	if (numoptions > 0)
 	{
-		reloptions = palloc(numoptions * sizeof(relopt_value));
+		reloptions = palloc_array(relopt_value, numoptions);
 
 		for (i = 0, j = 0; relOpts[i]; i++)
 		{
@@ -1700,7 +1700,7 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len,
 						option->gen->name)));
 
 	value_len = text_len - option->gen->namelen - 1;
-	value = (char *) palloc(value_len + 1);
+	value = palloc_array(char, value_len + 1);
 	memcpy(value, text_str + option->gen->namelen + 1, value_len);
 	value[value_len] = '\0';
 
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index 36026d3ec3f..a3f4c8f918e 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -366,7 +366,7 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc)
 
 		if ((cpy->num_defval = constr->num_defval) > 0)
 		{
-			cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
+			cpy->defval = palloc_array(AttrDefault, cpy->num_defval);
 			memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
 			for (i = cpy->num_defval - 1; i >= 0; i--)
 				cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
@@ -374,7 +374,7 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc)
 
 		if (constr->missing)
 		{
-			cpy->missing = (AttrMissing *) palloc(tupdesc->natts * sizeof(AttrMissing));
+			cpy->missing = palloc_array(AttrMissing, tupdesc->natts);
 			memcpy(cpy->missing, constr->missing, tupdesc->natts * sizeof(AttrMissing));
 			for (i = tupdesc->natts - 1; i >= 0; i--)
 			{
@@ -391,7 +391,7 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc)
 
 		if ((cpy->num_check = constr->num_check) > 0)
 		{
-			cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
+			cpy->check = palloc_array(ConstrCheck, cpy->num_check);
 			memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
 			for (i = cpy->num_check - 1; i >= 0; i--)
 			{
diff --git a/src/backend/access/gin/gindatapage.c b/src/backend/access/gin/gindatapage.c
index c5d7db28077..6a40da5eb04 100644
--- a/src/backend/access/gin/gindatapage.c
+++ b/src/backend/access/gin/gindatapage.c
@@ -168,7 +168,7 @@ GinDataLeafPageGetItems(Page page, int *nitems, ItemPointerData advancePast)
 	{
 		ItemPointer tmp = dataLeafPageGetUncompressed(page, nitems);
 
-		result = palloc((*nitems) * sizeof(ItemPointerData));
+		result = palloc_array(ItemPointerData, *nitems);
 		memcpy(result, tmp, (*nitems) * sizeof(ItemPointerData));
 	}
 
@@ -1418,7 +1418,7 @@ disassembleLeaf(Page page)
 
 			seginfo->action = GIN_SEGMENT_REPLACE;
 			seginfo->seg = NULL;
-			seginfo->items = palloc(nuncompressed * sizeof(ItemPointerData));
+			seginfo->items = palloc_array(ItemPointerData, nuncompressed);
 			memcpy(seginfo->items, uncompressed, nuncompressed * sizeof(ItemPointerData));
 			seginfo->nitems = nuncompressed;
 
diff --git a/src/backend/access/gin/ginfast.c b/src/backend/access/gin/ginfast.c
index f50848eb65a..b3c7c56f63d 100644
--- a/src/backend/access/gin/ginfast.c
+++ b/src/backend/access/gin/ginfast.c
@@ -365,7 +365,7 @@ ginHeapTupleFastInsert(GinState *ginstate, GinTupleCollector *collector)
 		off = (PageIsEmpty(page)) ? FirstOffsetNumber :
 			OffsetNumberNext(PageGetMaxOffsetNumber(page));
 
-		collectordata = ptr = (char *) palloc(collector->sumsize);
+		collectordata = ptr = palloc_array(char, collector->sumsize);
 
 		data.ntuples = collector->ntuples;
 
diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index b82f03a86b3..2bcb32ca3d0 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -542,7 +542,7 @@ startScanKey(GinState *ginstate, GinScanOpaque so, GinScanKey key)
 
 		key->nrequired = 0;
 		key->nadditional = key->nentries;
-		key->additionalEntries = palloc(key->nadditional * sizeof(GinScanEntry));
+		key->additionalEntries = palloc_array(GinScanEntry, key->nadditional);
 		for (int i = 0; i < key->nadditional; i++)
 			key->additionalEntries[i] = key->scanEntry[i];
 	}
@@ -578,8 +578,8 @@ startScanKey(GinState *ginstate, GinScanOpaque so, GinScanKey key)
 
 		key->nrequired = i + 1;
 		key->nadditional = key->nentries - key->nrequired;
-		key->requiredEntries = palloc(key->nrequired * sizeof(GinScanEntry));
-		key->additionalEntries = palloc(key->nadditional * sizeof(GinScanEntry));
+		key->requiredEntries = palloc_array(GinScanEntry, key->nrequired);
+		key->additionalEntries = palloc_array(GinScanEntry, key->nadditional);
 
 		j = 0;
 		for (int k = 0; k < key->nrequired; k++)
@@ -596,7 +596,7 @@ startScanKey(GinState *ginstate, GinScanOpaque so, GinScanKey key)
 
 		key->nrequired = 1;
 		key->nadditional = 0;
-		key->requiredEntries = palloc(1 * sizeof(GinScanEntry));
+		key->requiredEntries = palloc_array(GinScanEntry, 1);
 		key->requiredEntries[0] = key->scanEntry[0];
 	}
 	MemoryContextSwitchTo(oldCtx);
diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c
index 16abb76c001..ff192ce0855 100644
--- a/src/backend/access/gin/gininsert.c
+++ b/src/backend/access/gin/gininsert.c
@@ -1527,7 +1527,7 @@ GinBufferStoreTuple(GinBuffer *buffer, GinTuple *tup)
 		 * still pass 0 as number of elements in that array though.
 		 */
 		if (buffer->items == NULL)
-			buffer->items = palloc((buffer->nitems + tup->nitems) * sizeof(ItemPointerData));
+			buffer->items = palloc_array(ItemPointerData, buffer->nitems + tup->nitems);
 		else
 			buffer->items = repalloc(buffer->items,
 									 (buffer->nitems + tup->nitems) * sizeof(ItemPointerData));
diff --git a/src/backend/access/gin/ginpostinglist.c b/src/backend/access/gin/ginpostinglist.c
index d8dfcee4bde..5dcda40471a 100644
--- a/src/backend/access/gin/ginpostinglist.c
+++ b/src/backend/access/gin/ginpostinglist.c
@@ -308,7 +308,7 @@ ginPostingListDecodeAllSegments(GinPostingList *segment, int len, int *ndecoded_
 	 * Guess an initial size of the array.
 	 */
 	nallocated = segment->nbytes * 2 + 1;
-	result = palloc(nallocated * sizeof(ItemPointerData));
+	result = palloc_array(ItemPointerData, nallocated);
 
 	ndecoded = 0;
 	while ((char *) segment < endseg)
@@ -381,7 +381,7 @@ ginMergeItemPointers(ItemPointerData *a, uint32 na,
 {
 	ItemPointerData *dst;
 
-	dst = (ItemPointer) palloc((na + nb) * sizeof(ItemPointerData));
+	dst = palloc_array(ItemPointerData, na + nb);
 
 	/*
 	 * If the argument arrays don't overlap, we can just append them to each
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 075779b4b4f..1564b409bdb 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -281,15 +281,13 @@ ginNewScanKey(IndexScanDesc scan)
 	oldCtx = MemoryContextSwitchTo(so->keyCtx);
 
 	/* if no scan keys provided, allocate extra EVERYTHING GinScanKey */
-	so->keys = (GinScanKey)
-		palloc(Max(scan->numberOfKeys, 1) * sizeof(GinScanKeyData));
+	so->keys = palloc_array(GinScanKeyData, Max(scan->numberOfKeys, 1));
 	so->nkeys = 0;
 
 	/* initialize expansible array of GinScanEntry pointers */
 	so->totalentries = 0;
 	so->allocentries = 32;
-	so->entries = (GinScanEntry *)
-		palloc(so->allocentries * sizeof(GinScanEntry));
+	so->entries = palloc_array(GinScanEntry, so->allocentries);
 
 	so->isVoidRes = false;
 
@@ -357,7 +355,7 @@ ginNewScanKey(IndexScanDesc scan)
 		 * didn't create a nullFlags array, we assume everything is non-null.
 		 * While at it, detect whether any null keys are present.
 		 */
-		categories = (GinNullCategory *) palloc0(nQueryValues * sizeof(GinNullCategory));
+		categories = palloc0_array(GinNullCategory, nQueryValues);
 		if (nullFlags)
 		{
 			int32		j;
@@ -422,7 +420,7 @@ ginNewScanKey(IndexScanDesc scan)
 		/* We'd better have made at least one normal key */
 		Assert(numExcludeOnly < so->nkeys);
 		/* Make a temporary array to hold the re-ordered scan keys */
-		tmpkeys = (GinScanKey) palloc(so->nkeys * sizeof(GinScanKeyData));
+		tmpkeys = palloc_array(GinScanKeyData, so->nkeys);
 		/* Re-order the keys ... */
 		iNormalKey = 0;
 		iExcludeOnly = so->nkeys - numExcludeOnly;
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index e8a1e456287..5df2d402273 100644
--- a/src/backend/access/gist/gistget.c
+++ b/src/backend/access/gist/gistget.c
@@ -670,9 +670,7 @@ gistgettuple(IndexScanDesc scan, ScanDirection dir)
 						MemoryContext oldCxt =
 							MemoryContextSwitchTo(so->giststate->scanCxt);
 
-						so->killedItems =
-							(OffsetNumber *) palloc(MaxIndexTuplesPerPage
-													* sizeof(OffsetNumber));
+						so->killedItems = palloc_array(OffsetNumber, MaxIndexTuplesPerPage);
 
 						MemoryContextSwitchTo(oldCxt);
 					}
@@ -707,9 +705,7 @@ gistgettuple(IndexScanDesc scan, ScanDirection dir)
 					MemoryContext oldCxt =
 						MemoryContextSwitchTo(so->giststate->scanCxt);
 
-					so->killedItems =
-						(OffsetNumber *) palloc(MaxIndexTuplesPerPage
-												* sizeof(OffsetNumber));
+					so->killedItems = palloc_array(OffsetNumber, MaxIndexTuplesPerPage);
 
 					MemoryContextSwitchTo(oldCxt);
 				}
diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c
index bb84030b23d..ed3561f6f60 100644
--- a/src/backend/access/gist/gistproc.c
+++ b/src/backend/access/gist/gistproc.c
@@ -516,8 +516,8 @@ gist_box_picksplit(PG_FUNCTION_ARGS)
 	nentries = context.entriesCount = maxoff - FirstOffsetNumber + 1;
 
 	/* Allocate arrays for intervals along axes */
-	intervalsLower = (SplitInterval *) palloc(nentries * sizeof(SplitInterval));
-	intervalsUpper = (SplitInterval *) palloc(nentries * sizeof(SplitInterval));
+	intervalsLower = palloc_array(SplitInterval, nentries);
+	intervalsUpper = palloc_array(SplitInterval, nentries);
 
 	/*
 	 * Calculate the overall minimum bounding box over all the entries.
@@ -693,8 +693,8 @@ gist_box_picksplit(PG_FUNCTION_ARGS)
 	 */
 
 	/* Allocate vectors for results */
-	v->spl_left = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
-	v->spl_right = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
+	v->spl_left = palloc_array(OffsetNumber, nentries);
+	v->spl_right = palloc_array(OffsetNumber, nentries);
 	v->spl_nleft = 0;
 	v->spl_nright = 0;
 
@@ -707,7 +707,7 @@ gist_box_picksplit(PG_FUNCTION_ARGS)
 	 * either group without affecting overlap along selected axis.
 	 */
 	commonEntriesCount = 0;
-	commonEntries = (CommonEntry *) palloc(nentries * sizeof(CommonEntry));
+	commonEntries = palloc_array(CommonEntry, nentries);
 
 	/* Helper macros to place an entry in the left or right group */
 #define PLACE_LEFT(box, off)					\
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
index c65f93abdae..5583a5a35a4 100644
--- a/src/backend/access/gist/gistscan.c
+++ b/src/backend/access/gist/gistscan.c
@@ -97,7 +97,7 @@ gistbeginscan(Relation r, int nkeys, int norderbys)
 	so->queueCxt = giststate->scanCxt;	/* see gistrescan */
 
 	/* workspaces with size dependent on numberOfOrderBys: */
-	so->distances = palloc(sizeof(so->distances[0]) * scan->numberOfOrderBys);
+	so->distances = palloc_array(IndexOrderByDistance, scan->numberOfOrderBys);
 	so->qual_ok = true;			/* in case there are zero keys */
 	if (scan->numberOfOrderBys > 0)
 	{
@@ -229,7 +229,7 @@ gistrescan(IndexScanDesc scan, ScanKey key, int nkeys,
 		 */
 		if (!first_time)
 		{
-			fn_extras = (void **) palloc(scan->numberOfKeys * sizeof(void *));
+			fn_extras = palloc_array(void *, scan->numberOfKeys);
 			for (i = 0; i < scan->numberOfKeys; i++)
 				fn_extras[i] = scan->keyData[i].sk_func.fn_extra;
 		}
@@ -284,14 +284,14 @@ gistrescan(IndexScanDesc scan, ScanKey key, int nkeys,
 		/* As above, preserve fn_extra if not first time through */
 		if (!first_time)
 		{
-			fn_extras = (void **) palloc(scan->numberOfOrderBys * sizeof(void *));
+			fn_extras = palloc_array(void *, scan->numberOfOrderBys);
 			for (i = 0; i < scan->numberOfOrderBys; i++)
 				fn_extras[i] = scan->orderByData[i].sk_func.fn_extra;
 		}
 
 		memcpy(scan->orderByData, orderbys, scan->numberOfOrderBys * sizeof(ScanKeyData));
 
-		so->orderByTypes = (Oid *) palloc(scan->numberOfOrderBys * sizeof(Oid));
+		so->orderByTypes = palloc_array(Oid, scan->numberOfOrderBys);
 
 		/*
 		 * Modify the order-by key so that the Distance method is called for
diff --git a/src/backend/access/gist/gistsplit.c b/src/backend/access/gist/gistsplit.c
index dc899565320..48eff023826 100644
--- a/src/backend/access/gist/gistsplit.c
+++ b/src/backend/access/gist/gistsplit.c
@@ -587,8 +587,8 @@ gistSplitHalf(GIST_SPLITVEC *v, int len)
 	int			i;
 
 	v->spl_nright = v->spl_nleft = 0;
-	v->spl_left = (OffsetNumber *) palloc(len * sizeof(OffsetNumber));
-	v->spl_right = (OffsetNumber *) palloc(len * sizeof(OffsetNumber));
+	v->spl_left = palloc_array(OffsetNumber, len);
+	v->spl_right = palloc_array(OffsetNumber, len);
 	for (i = 1; i <= len; i++)
 		if (i < len / 2)
 			v->spl_right[v->spl_nright++] = i;
@@ -632,7 +632,7 @@ gistSplitByKey(Relation r, Page page, IndexTuple *itup, int len,
 	/* note that entryvec->vector[0] goes unused in this code */
 	entryvec = palloc(GEVHDRSZ + (len + 1) * sizeof(GISTENTRY));
 	entryvec->n = len + 1;
-	offNullTuples = (OffsetNumber *) palloc(len * sizeof(OffsetNumber));
+	offNullTuples = palloc_array(OffsetNumber, len);
 
 	for (i = 1; i <= len; i++)
 	{
@@ -674,7 +674,7 @@ gistSplitByKey(Relation r, Page page, IndexTuple *itup, int len,
 		v->splitVector.spl_nright = nOffNullTuples;
 		v->spl_risnull[attno] = true;
 
-		v->splitVector.spl_left = (OffsetNumber *) palloc(len * sizeof(OffsetNumber));
+		v->splitVector.spl_left = palloc_array(OffsetNumber, len);
 		v->splitVector.spl_nleft = 0;
 		for (i = 1; i <= len; i++)
 			if (j < v->splitVector.spl_nright && offNullTuples[j] == i)
@@ -716,8 +716,8 @@ gistSplitByKey(Relation r, Page page, IndexTuple *itup, int len,
 				 * Form an array of just the don't-care tuples to pass to a
 				 * recursive invocation of this function for the next column.
 				 */
-				IndexTuple *newitup = (IndexTuple *) palloc(len * sizeof(IndexTuple));
-				OffsetNumber *map = (OffsetNumber *) palloc(len * sizeof(OffsetNumber));
+				IndexTuple *newitup = palloc_array(IndexTuple, len);
+				OffsetNumber *map = palloc_array(OffsetNumber, len);
 				int			newlen = 0;
 				GIST_SPLITVEC backupSplit;
 
diff --git a/src/backend/access/gist/gistxlog.c b/src/backend/access/gist/gistxlog.c
index ae538dc81ca..171e0d4d1b4 100644
--- a/src/backend/access/gist/gistxlog.c
+++ b/src/backend/access/gist/gistxlog.c
@@ -228,7 +228,7 @@ decodePageSplitRecord(char *begin, int len, int *n)
 	memcpy(n, begin, sizeof(int));
 	ptr = begin + sizeof(int);
 
-	tuples = palloc(*n * sizeof(IndexTuple));
+	tuples = palloc_array(IndexTuple, *n);
 
 	for (i = 0; i < *n; i++)
 	{
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 8b488cfd8f6..e399d41332c 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -2333,7 +2333,7 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples,
 												   HEAP_DEFAULT_FILLFACTOR);
 
 	/* Toast and set header data in all the slots */
-	heaptuples = palloc(ntuples * sizeof(HeapTuple));
+	heaptuples = palloc_array(HeapTuple, ntuples);
 	for (i = 0; i < ntuples; i++)
 	{
 		HeapTuple	tuple;
@@ -8979,7 +8979,7 @@ bottomup_sort_and_shrink(TM_IndexDeleteOp *delstate)
 	/* Sort groups and rearrange caller's deltids array */
 	qsort(blockgroups, nblockgroups, sizeof(IndexDeleteCounts),
 		  bottomup_sort_and_shrink_cmp);
-	reordereddeltids = palloc(delstate->ndeltids * sizeof(TM_IndexDelete));
+	reordereddeltids = palloc_array(TM_IndexDelete, delstate->ndeltids);
 
 	nblockgroups = Min(BOTTOMUP_MAX_NBLOCKS, nblockgroups);
 	/* Determine number of favorable blocks at the start of final deltids */
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 9bce43e563c..063ef2208de 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -760,8 +760,7 @@ heap_vacuum_rel(Relation rel, const VacuumParams *params,
 	/* Allocate/initialize output statistics state */
 	vacrel->new_rel_tuples = 0;
 	vacrel->new_live_tuples = 0;
-	vacrel->indstats = (IndexBulkDeleteResult **)
-		palloc0(vacrel->nindexes * sizeof(IndexBulkDeleteResult *));
+	vacrel->indstats = palloc0_array(IndexBulkDeleteResult *, vacrel->nindexes);
 
 	/* Initialize remaining counters (be tidy) */
 	vacrel->num_index_scans = 0;
diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index c8af97dd23d..35568f66eb7 100644
--- a/src/backend/access/nbtree/nbtinsert.c
+++ b/src/backend/access/nbtree/nbtinsert.c
@@ -2876,8 +2876,8 @@ _bt_simpledel_pass(Relation rel, Buffer buffer, Relation heapRel,
 	delstate.bottomup = false;
 	delstate.bottomupfreespace = 0;
 	delstate.ndeltids = 0;
-	delstate.deltids = palloc(MaxTIDsPerBTreePage * sizeof(TM_IndexDelete));
-	delstate.status = palloc(MaxTIDsPerBTreePage * sizeof(TM_IndexStatus));
+	delstate.deltids = palloc_array(TM_IndexDelete, MaxTIDsPerBTreePage);
+	delstate.status = palloc_array(TM_IndexStatus, MaxTIDsPerBTreePage);
 
 	for (offnum = minoff;
 		 offnum <= maxoff;
diff --git a/src/backend/access/nbtree/nbtpreprocesskeys.c b/src/backend/access/nbtree/nbtpreprocesskeys.c
index 39c0a5d610f..65f983ca4b8 100644
--- a/src/backend/access/nbtree/nbtpreprocesskeys.c
+++ b/src/backend/access/nbtree/nbtpreprocesskeys.c
@@ -1568,7 +1568,7 @@ _bt_unmark_keys(IndexScanDesc scan, int *keyDataMap)
 	 * Any requiredness markings that we might leave on later keys/attributes
 	 * are predicated on there being required = keys on all prior columns.
 	 */
-	unmarkikey = palloc0(so->numberOfKeys * sizeof(bool));
+	unmarkikey = palloc0_array(bool, so->numberOfKeys);
 	nunmark = 0;
 
 	/* Set things up for first key's attribute */
@@ -1653,14 +1653,14 @@ _bt_unmark_keys(IndexScanDesc scan, int *keyDataMap)
 	 * Next, allocate temp arrays: one for required keys that'll remain
 	 * required, the other for all remaining keys
 	 */
-	unmarkKeys = palloc(nunmark * sizeof(ScanKeyData));
-	keepKeys = palloc((so->numberOfKeys - nunmark) * sizeof(ScanKeyData));
+	unmarkKeys = palloc_array(ScanKeyData, nunmark);
+	keepKeys = palloc_array(ScanKeyData, so->numberOfKeys - nunmark);
 	nunmarked = 0;
 	nkept = 0;
 	if (so->numArrayKeys)
 	{
-		unmarkOrderProcs = palloc(nunmark * sizeof(FmgrInfo));
-		keepOrderProcs = palloc((so->numberOfKeys - nunmark) * sizeof(FmgrInfo));
+		unmarkOrderProcs = palloc_array(FmgrInfo, nunmark);
+		keepOrderProcs = palloc_array(FmgrInfo, so->numberOfKeys - nunmark);
 	}
 
 	/*
@@ -1890,13 +1890,13 @@ _bt_preprocess_array_keys(IndexScanDesc scan, int *new_numberOfKeys)
 	oldContext = MemoryContextSwitchTo(so->arrayContext);
 
 	/* Create output scan keys in the workspace context */
-	arrayKeyData = (ScanKey) palloc(numArrayKeyData * sizeof(ScanKeyData));
+	arrayKeyData = (ScanKey) palloc_array(ScanKeyData, numArrayKeyData);
 
 	/* Allocate space for per-array data in the workspace context */
-	so->arrayKeys = (BTArrayKeyInfo *) palloc(numArrayKeys * sizeof(BTArrayKeyInfo));
+	so->arrayKeys = palloc_array(BTArrayKeyInfo, numArrayKeys);
 
 	/* Allocate space for ORDER procs used to help _bt_checkkeys */
-	so->orderProcs = (FmgrInfo *) palloc(numArrayKeyData * sizeof(FmgrInfo));
+	so->orderProcs = palloc_array(FmgrInfo, numArrayKeyData);
 
 	numArrayKeys = 0;
 	numArrayKeyData = 0;
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index 3df2c752ead..60b6c290769 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -352,7 +352,7 @@ btbeginscan(Relation rel, int nkeys, int norderbys)
 	BTScanPosInvalidate(so->currPos);
 	BTScanPosInvalidate(so->markPos);
 	if (scan->numberOfKeys > 0)
-		so->keyData = (ScanKey) palloc(scan->numberOfKeys * sizeof(ScanKeyData));
+		so->keyData = palloc_array(ScanKeyData, scan->numberOfKeys);
 	else
 		so->keyData = NULL;
 
@@ -435,7 +435,7 @@ btrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
 	 */
 	if (scan->xs_want_itup && so->currTuples == NULL)
 	{
-		so->currTuples = (char *) palloc(BLCKSZ * 2);
+		so->currTuples = palloc_array(char, BLCKSZ * 2);
 		so->markTuples = so->currTuples + BLCKSZ;
 	}
 
diff --git a/src/backend/access/spgist/spgdoinsert.c b/src/backend/access/spgist/spgdoinsert.c
index 7c7371c69e8..8aa5cc86563 100644
--- a/src/backend/access/spgist/spgdoinsert.c
+++ b/src/backend/access/spgist/spgdoinsert.c
@@ -1126,7 +1126,7 @@ doPickSplit(Relation index, SpGistState *state,
 	xlrec.storesNulls = isNulls;
 	xlrec.isRootSplit = SpGistBlockIsRoot(current->blkno);
 
-	leafdata = leafptr = (char *) palloc(totalLeafSizes);
+	leafdata = leafptr = palloc_array(char, totalLeafSizes);
 
 	/* Here we begin making the changes to the target pages */
 	START_CRIT_SECTION();
diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c
index e00feff0bb3..e7f9937f6e4 100644
--- a/src/backend/access/spgist/spgtextproc.c
+++ b/src/backend/access/spgist/spgtextproc.c
@@ -116,7 +116,7 @@ formTextDatum(const char *data, int datalen)
 {
 	char	   *p;
 
-	p = (char *) palloc(datalen + VARHDRSZ);
+	p = palloc_array(char, datalen + VARHDRSZ);
 
 	if (datalen + VARHDRSZ_SHORT <= VARATT_SHORT_MAX)
 	{
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 424516dc106..d688815083c 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -1337,7 +1337,7 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
 	length = nextMXOffset - offset;
 
 	/* read the members */
-	ptr = (MultiXactMember *) palloc(length * sizeof(MultiXactMember));
+	ptr = palloc_array(MultiXactMember, length);
 	prev_pageno = -1;
 	for (int i = 0; i < length; i++, offset++)
 	{
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index fa3bc50ec48..d088ea0ebcc 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -1357,7 +1357,7 @@ ReadTwoPhaseFile(FullTransactionId fxid, bool missing_ok)
 	 * OK, slurp in the file.
 	 */
 	buflen = stat.st_size;
-	buf = (char *) palloc(buflen);
+	buf = palloc_array(char, buflen);
 
 	pgstat_report_wait_start(WAIT_EVENT_TWOPHASE_FILE_READ);
 	r = read(fd, buf, buflen);
@@ -2012,7 +2012,7 @@ PrescanPreparedTransactions(TransactionId **xids_p, int *nxids_p)
 				if (nxids == 0)
 				{
 					allocsize = 10;
-					xids = palloc(allocsize * sizeof(TransactionId));
+					xids = palloc_array(TransactionId, allocsize);
 				}
 				else
 				{
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 3a89149016f..1b2b13ddbe6 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -5640,7 +5640,7 @@ SerializeTransactionState(Size maxsize, char *start_address)
 		   <= maxsize);
 
 	/* Copy them to our scratch space. */
-	workspace = palloc(nxids * sizeof(TransactionId));
+	workspace = palloc_array(TransactionId, nxids);
 	for (s = CurrentTransactionState; s != NULL; s = s->parent)
 	{
 		if (FullTransactionIdIsValid(s->fullTransactionId))
diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c
index 4bfe8607f4e..2cfce115865 100644
--- a/src/backend/access/transam/xlogreader.c
+++ b/src/backend/access/transam/xlogreader.c
@@ -203,7 +203,7 @@ allocate_recordbuf(XLogReaderState *state, uint32 reclength)
 
 	if (state->readRecordBuf)
 		pfree(state->readRecordBuf);
-	state->readRecordBuf = (char *) palloc(newSize);
+	state->readRecordBuf = palloc_array(char, newSize);
 	state->readRecordBufSize = newSize;
 }
 
diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
index 6de13b91748..4f82a18add0 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -537,8 +537,8 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
 	 * (2) a static char array isn't guaranteed to have any particular
 	 * alignment, whereas palloc() will provide MAXALIGN'd storage.
 	 */
-	replay_image_masked = (char *) palloc(BLCKSZ);
-	primary_image_masked = (char *) palloc(BLCKSZ);
+	replay_image_masked = palloc_array(char, BLCKSZ);
+	primary_image_masked = palloc_array(char, BLCKSZ);
 
 	/*
 	 * Read the backup_label file.  We want to run this part of the recovery
diff --git a/src/backend/backup/basebackup_incremental.c b/src/backend/backup/basebackup_incremental.c
index 9235f6b268c..27fc42a2a43 100644
--- a/src/backend/backup/basebackup_incremental.c
+++ b/src/backend/backup/basebackup_incremental.c
@@ -310,7 +310,7 @@ PrepareForIncrementalBackup(IncrementalBackupInfo *ib,
 	 * to the beginning.
 	 */
 	expectedTLEs = readTimeLineHistory(backup_state->starttli);
-	tlep = palloc0(num_wal_ranges * sizeof(TimeLineHistoryEntry *));
+	tlep = palloc0_array(TimeLineHistoryEntry *, num_wal_ranges);
 	for (int i = 0; i < num_wal_ranges; ++i)
 	{
 		backup_wal_range *range = list_nth(ib->manifest_wal_ranges, i);
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 427213ecf1f..91b02317ce7 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -1927,7 +1927,7 @@ ExecGrant_Relation(InternalGrant *istmt)
 		 * corresponds to FirstLowInvalidHeapAttributeNumber.
 		 */
 		num_col_privileges = pg_class_tuple->relnatts - FirstLowInvalidHeapAttributeNumber + 1;
-		col_privileges = (AclMode *) palloc0(num_col_privileges * sizeof(AclMode));
+		col_privileges = palloc0_array(AclMode, num_col_privileges);
 		have_col_privileges = false;
 
 		/*
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 88087654de9..f2fd4aee29f 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -2194,7 +2194,7 @@ StoreRelCheck(Relation rel, const char *ccname, Node *expr,
 		ListCell   *vl;
 		int			i = 0;
 
-		attNos = (int16 *) palloc(keycount * sizeof(int16));
+		attNos = palloc_array(int16, keycount);
 		foreach(vl, varList)
 		{
 			Var		   *var = (Var *) lfirst(vl);
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 56b87d878e8..f21dce6a23b 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -1650,7 +1650,7 @@ MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
 	Assert(include_out_arguments ? (pronargs == pronallargs) : (pronargs <= pronallargs));
 
 	/* initialize state for matching */
-	*argnumbers = (int *) palloc(pronargs * sizeof(int));
+	*argnumbers = palloc_array(int, pronargs);
 	memset(arggiven, false, pronargs * sizeof(bool));
 
 	/* there are numposargs positional args before the named args */
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index b12765ae691..a21d673a65a 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -118,7 +118,7 @@ CreateConstraintEntry(const char *constraintName,
 	{
 		Datum	   *conkey;
 
-		conkey = (Datum *) palloc(constraintNKeys * sizeof(Datum));
+		conkey = palloc_array(Datum, constraintNKeys);
 		for (i = 0; i < constraintNKeys; i++)
 			conkey[i] = Int16GetDatum(constraintKey[i]);
 		conkeyArray = construct_array_builtin(conkey, constraintNKeys, INT2OID);
@@ -131,7 +131,7 @@ CreateConstraintEntry(const char *constraintName,
 		Datum	   *fkdatums;
 		int			nkeys = Max(foreignNKeys, numFkDeleteSetCols);
 
-		fkdatums = (Datum *) palloc(nkeys * sizeof(Datum));
+		fkdatums = palloc_array(Datum, nkeys);
 		for (i = 0; i < foreignNKeys; i++)
 			fkdatums[i] = Int16GetDatum(foreignKey[i]);
 		confkeyArray = construct_array_builtin(fkdatums, foreignNKeys, INT2OID);
@@ -167,7 +167,7 @@ CreateConstraintEntry(const char *constraintName,
 	{
 		Datum	   *opdatums;
 
-		opdatums = (Datum *) palloc(constraintNKeys * sizeof(Datum));
+		opdatums = palloc_array(Datum, constraintNKeys);
 		for (i = 0; i < constraintNKeys; i++)
 			opdatums[i] = ObjectIdGetDatum(exclOp[i]);
 		conexclopArray = construct_array_builtin(opdatums, constraintNKeys, OIDOID);
diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c
index 4b9802aafcc..d7a604cf750 100644
--- a/src/backend/catalog/pg_inherits.c
+++ b/src/backend/catalog/pg_inherits.c
@@ -106,7 +106,7 @@ find_inheritance_children_extended(Oid parentrelId, bool omit_detached,
 	 * Scan pg_inherits and build a working array of subclass OIDs.
 	 */
 	maxoids = 32;
-	oidarr = (Oid *) palloc(maxoids * sizeof(Oid));
+	oidarr = palloc_array(Oid, maxoids);
 	numoids = 0;
 
 	relation = table_open(InheritsRelationId, AccessShareLock);
diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c
index c9998531b2f..6a8b0fc66ae 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -716,8 +716,7 @@ checkSharedDependencies(Oid classId, Oid objectId,
 #define MAX_REPORTED_DEPS 100
 
 	allocedobjects = 128;		/* arbitrary initial array size */
-	objects = (ShDependObjectInfo *)
-		palloc(allocedobjects * sizeof(ShDependObjectInfo));
+	objects = palloc_array(ShDependObjectInfo, allocedobjects);
 	numobjects = 0;
 	initStringInfo(&descs);
 	initStringInfo(&alldescs);
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index 74ceb5fe20d..26e05f061e2 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -318,9 +318,9 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
 	}
 
 	/* Build modified tuple */
-	values = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(Datum));
-	nulls = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
-	replaces = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
+	values = palloc0_array(Datum, RelationGetNumberOfAttributes(rel));
+	nulls = palloc0_array(bool, RelationGetNumberOfAttributes(rel));
+	replaces = palloc0_array(bool, RelationGetNumberOfAttributes(rel));
 	namestrcpy(&nameattrdata, new_name);
 	values[Anum_name - 1] = NameGetDatum(&nameattrdata);
 	replaces[Anum_name - 1] = true;
@@ -798,9 +798,9 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
 								  nspOid);
 
 	/* Build modified tuple */
-	values = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(Datum));
-	nulls = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
-	replaces = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
+	values = palloc0_array(Datum, RelationGetNumberOfAttributes(rel));
+	nulls = palloc0_array(bool, RelationGetNumberOfAttributes(rel));
+	replaces = palloc0_array(bool, RelationGetNumberOfAttributes(rel));
 	values[Anum_namespace - 1] = ObjectIdGetDatum(nspOid);
 	replaces[Anum_namespace - 1] = true;
 	newtup = heap_modify_tuple(tup, RelationGetDescr(rel),
@@ -1024,9 +1024,9 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
 
 		/* Build a modified tuple */
 		nattrs = RelationGetNumberOfAttributes(rel);
-		values = palloc0(nattrs * sizeof(Datum));
-		nulls = palloc0(nattrs * sizeof(bool));
-		replaces = palloc0(nattrs * sizeof(bool));
+		values = palloc0_array(Datum, nattrs);
+		nulls = palloc0_array(bool, nattrs);
+		replaces = palloc0_array(bool, nattrs);
 		values[Anum_owner - 1] = ObjectIdGetDatum(new_ownerId);
 		replaces[Anum_owner - 1] = true;
 
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index c28b9dae983..c3ad6d33e86 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -397,8 +397,7 @@ do_analyze_rel(Relation onerel, const VacuumParams *params,
 	{
 		ListCell   *le;
 
-		vacattrstats = (VacAttrStats **) palloc(list_length(va_cols) *
-												sizeof(VacAttrStats *));
+		vacattrstats = palloc_array(VacAttrStats *, list_length(va_cols));
 		tcnt = 0;
 		foreach(le, va_cols)
 		{
@@ -415,8 +414,7 @@ do_analyze_rel(Relation onerel, const VacuumParams *params,
 	else
 	{
 		attr_cnt = onerel->rd_att->natts;
-		vacattrstats = (VacAttrStats **)
-			palloc(attr_cnt * sizeof(VacAttrStats *));
+		vacattrstats = palloc_array(VacAttrStats *, attr_cnt);
 		tcnt = 0;
 		for (i = 1; i <= attr_cnt; i++)
 		{
@@ -459,7 +457,7 @@ do_analyze_rel(Relation onerel, const VacuumParams *params,
 	indexdata = NULL;
 	if (nindexes > 0)
 	{
-		indexdata = (AnlIndexData *) palloc0(nindexes * sizeof(AnlIndexData));
+		indexdata = palloc0_array(AnlIndexData, nindexes);
 		for (ind = 0; ind < nindexes; ind++)
 		{
 			AnlIndexData *thisdata = &indexdata[ind];
@@ -471,8 +469,8 @@ do_analyze_rel(Relation onerel, const VacuumParams *params,
 			{
 				ListCell   *indexpr_item = list_head(indexInfo->ii_Expressions);
 
-				thisdata->vacattrstats = (VacAttrStats **)
-					palloc(indexInfo->ii_NumIndexAttrs * sizeof(VacAttrStats *));
+				thisdata->vacattrstats = palloc_array(VacAttrStats *,
+													  indexInfo->ii_NumIndexAttrs);
 				tcnt = 0;
 				for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
 				{
@@ -535,7 +533,7 @@ do_analyze_rel(Relation onerel, const VacuumParams *params,
 	/*
 	 * Acquire the sample rows
 	 */
-	rows = (HeapTuple *) palloc(targrows * sizeof(HeapTuple));
+	rows = palloc_array(HeapTuple, targrows);
 	pgstat_progress_update_param(PROGRESS_ANALYZE_PHASE,
 								 inh ? PROGRESS_ANALYZE_PHASE_ACQUIRE_SAMPLE_ROWS_INH :
 								 PROGRESS_ANALYZE_PHASE_ACQUIRE_SAMPLE_ROWS);
@@ -930,8 +928,8 @@ compute_index_stats(Relation onerel, double totalrows,
 		predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
 
 		/* Compute and save index expression values */
-		exprvals = (Datum *) palloc(numrows * attr_cnt * sizeof(Datum));
-		exprnulls = (bool *) palloc(numrows * attr_cnt * sizeof(bool));
+		exprvals = palloc_array(Datum, numrows * attr_cnt);
+		exprnulls = palloc_array(bool, numrows * attr_cnt);
 		numindexrows = 0;
 		tcnt = 0;
 		for (rowno = 0; rowno < numrows; rowno++)
@@ -1497,10 +1495,9 @@ acquire_inherited_sample_rows(Relation onerel, int elevel,
 	 * Identify acquirefuncs to use, and count blocks in all the relations.
 	 * The result could overflow BlockNumber, so we use double arithmetic.
 	 */
-	rels = (Relation *) palloc(list_length(tableOIDs) * sizeof(Relation));
-	acquirefuncs = (AcquireSampleRowsFunc *)
-		palloc(list_length(tableOIDs) * sizeof(AcquireSampleRowsFunc));
-	relblocks = (double *) palloc(list_length(tableOIDs) * sizeof(double));
+	rels = palloc_array(Relation, list_length(tableOIDs));
+	acquirefuncs = palloc_array(AcquireSampleRowsFunc, list_length(tableOIDs));
+	relblocks = palloc_array(double, list_length(tableOIDs));
 	totalblocks = 0;
 	nrels = 0;
 	has_child = false;
@@ -1775,7 +1772,7 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
 			if (stats->stanumbers[k] != NULL)
 			{
 				int			nnum = stats->numnumbers[k];
-				Datum	   *numdatums = (Datum *) palloc(nnum * sizeof(Datum));
+				Datum	   *numdatums = palloc_array(Datum, nnum);
 				ArrayType  *arry;
 
 				for (n = 0; n < nnum; n++)
@@ -2148,7 +2145,7 @@ compute_distinct_stats(VacAttrStatsP stats,
 	track_max = 2 * num_mcv;
 	if (track_max < 10)
 		track_max = 10;
-	track = (TrackItem *) palloc(track_max * sizeof(TrackItem));
+	track = palloc_array(TrackItem, track_max);
 	track_cnt = 0;
 
 	fmgr_info(mystats->eqfunc, &f_cmpeq);
@@ -2385,7 +2382,7 @@ compute_distinct_stats(VacAttrStatsP stats,
 
 			if (num_mcv > 0)
 			{
-				mcv_counts = (int *) palloc(num_mcv * sizeof(int));
+				mcv_counts = palloc_array(int, num_mcv);
 				for (i = 0; i < num_mcv; i++)
 					mcv_counts[i] = track[i].count;
 
@@ -2405,8 +2402,8 @@ compute_distinct_stats(VacAttrStatsP stats,
 
 			/* Must copy the target values into anl_context */
 			old_context = MemoryContextSwitchTo(stats->anl_context);
-			mcv_values = (Datum *) palloc(num_mcv * sizeof(Datum));
-			mcv_freqs = (float4 *) palloc(num_mcv * sizeof(float4));
+			mcv_values = palloc_array(Datum, num_mcv);
+			mcv_freqs = palloc_array(float4, num_mcv);
 			for (i = 0; i < num_mcv; i++)
 			{
 				mcv_values[i] = datumCopy(track[i].value,
@@ -2484,9 +2481,9 @@ compute_scalar_stats(VacAttrStatsP stats,
 	int			num_bins = stats->attstattarget;
 	StdAnalyzeData *mystats = (StdAnalyzeData *) stats->extra_data;
 
-	values = (ScalarItem *) palloc(samplerows * sizeof(ScalarItem));
-	tupnoLink = (int *) palloc(samplerows * sizeof(int));
-	track = (ScalarMCVItem *) palloc(num_mcv * sizeof(ScalarMCVItem));
+	values = palloc_array(ScalarItem, samplerows);
+	tupnoLink = palloc_array(int, samplerows);
+	track = palloc_array(ScalarMCVItem, num_mcv);
 
 	memset(&ssup, 0, sizeof(ssup));
 	ssup.ssup_cxt = CurrentMemoryContext;
@@ -2750,7 +2747,7 @@ compute_scalar_stats(VacAttrStatsP stats,
 
 			if (num_mcv > 0)
 			{
-				mcv_counts = (int *) palloc(num_mcv * sizeof(int));
+				mcv_counts = palloc_array(int, num_mcv);
 				for (i = 0; i < num_mcv; i++)
 					mcv_counts[i] = track[i].count;
 
@@ -2770,8 +2767,8 @@ compute_scalar_stats(VacAttrStatsP stats,
 
 			/* Must copy the target values into anl_context */
 			old_context = MemoryContextSwitchTo(stats->anl_context);
-			mcv_values = (Datum *) palloc(num_mcv * sizeof(Datum));
-			mcv_freqs = (float4 *) palloc(num_mcv * sizeof(float4));
+			mcv_values = palloc_array(Datum, num_mcv);
+			mcv_freqs = palloc_array(float4, num_mcv);
 			for (i = 0; i < num_mcv; i++)
 			{
 				mcv_values[i] = datumCopy(values[track[i].first].value,
@@ -2865,7 +2862,7 @@ compute_scalar_stats(VacAttrStatsP stats,
 
 			/* Must copy the target values into anl_context */
 			old_context = MemoryContextSwitchTo(stats->anl_context);
-			hist_values = (Datum *) palloc(num_hist * sizeof(Datum));
+			hist_values = palloc_array(Datum, num_hist);
 
 			/*
 			 * The object of this loop is to copy the first and last values[]
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index 0bc31ec2b6f..b6f3bc9185b 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -867,7 +867,7 @@ pg_import_system_collations(PG_FUNCTION_ARGS)
 
 		/* expansible array of aliases */
 		maxaliases = 100;
-		aliases = (CollAliasData *) palloc(maxaliases * sizeof(CollAliasData));
+		aliases = palloc_array(CollAliasData, maxaliases);
 		naliases = 0;
 
 		locale_a_handle = OpenPipeStream("locale -a", "r");
diff --git a/src/backend/commands/copyfrom.c b/src/backend/commands/copyfrom.c
index 80a527ed4c6..6297a0b06f0 100644
--- a/src/backend/commands/copyfrom.c
+++ b/src/backend/commands/copyfrom.c
@@ -179,7 +179,7 @@ CopyFromTextLikeStart(CopyFromState cstate, TupleDesc tupDesc)
 	 */
 	if (cstate->need_transcoding)
 	{
-		cstate->input_buf = (char *) palloc(INPUT_BUF_SIZE + 1);
+		cstate->input_buf = palloc_array(char, INPUT_BUF_SIZE + 1);
 		cstate->input_buf_index = cstate->input_buf_len = 0;
 	}
 	else
@@ -194,7 +194,7 @@ CopyFromTextLikeStart(CopyFromState cstate, TupleDesc tupDesc)
 	 */
 	attr_count = list_length(cstate->attnumlist);
 	cstate->max_fields = attr_count;
-	cstate->raw_fields = (char **) palloc(attr_count * sizeof(char *));
+	cstate->raw_fields = palloc_array(char *, attr_count);
 }
 
 /*
@@ -350,7 +350,7 @@ CopyLimitPrintoutLength(const char *str)
 	/*
 	 * Truncate, and add "..." to show we truncated the input.
 	 */
-	res = (char *) palloc(len + 4);
+	res = palloc_array(char, len + 4);
 	memcpy(res, str, len);
 	strcpy(res + len, "...");
 
@@ -1595,7 +1595,7 @@ BeginCopyFrom(ParseState *pstate,
 	num_phys_attrs = tupDesc->natts;
 
 	/* Convert FORCE_NOT_NULL name list to per-column flags, check validity */
-	cstate->opts.force_notnull_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
+	cstate->opts.force_notnull_flags = palloc0_array(bool, num_phys_attrs);
 	if (cstate->opts.force_notnull_all)
 		MemSet(cstate->opts.force_notnull_flags, true, num_phys_attrs * sizeof(bool));
 	else if (cstate->opts.force_notnull)
@@ -1655,7 +1655,7 @@ BeginCopyFrom(ParseState *pstate,
 	}
 
 	/* Convert FORCE_NULL name list to per-column flags, check validity */
-	cstate->opts.force_null_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
+	cstate->opts.force_null_flags = palloc0_array(bool, num_phys_attrs);
 	if (cstate->opts.force_null_all)
 		MemSet(cstate->opts.force_null_flags, true, num_phys_attrs * sizeof(bool));
 	else if (cstate->opts.force_null)
@@ -1686,7 +1686,7 @@ BeginCopyFrom(ParseState *pstate,
 		List	   *attnums;
 		ListCell   *cur;
 
-		cstate->convert_select_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
+		cstate->convert_select_flags = palloc0_array(bool, num_phys_attrs);
 
 		attnums = CopyGetAttnums(tupDesc, cstate->rel, cstate->opts.convert_select);
 
@@ -1751,7 +1751,7 @@ BeginCopyFrom(ParseState *pstate,
 	 * attribute_buf and raw_buf are used in both text and binary modes, but
 	 * input_buf and line_buf only in text mode.
 	 */
-	cstate->raw_buf = palloc(RAW_BUF_SIZE + 1);
+	cstate->raw_buf = palloc_array(char, RAW_BUF_SIZE + 1);
 	cstate->raw_buf_index = cstate->raw_buf_len = 0;
 	cstate->raw_reached_eof = false;
 
@@ -1773,10 +1773,10 @@ BeginCopyFrom(ParseState *pstate,
 	 * the input function), and info about defaults and constraints. (Which
 	 * input function we use depends on text/binary format choice.)
 	 */
-	in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
-	typioparams = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
-	defmap = (int *) palloc(num_phys_attrs * sizeof(int));
-	defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *));
+	in_functions = palloc_array(FmgrInfo, num_phys_attrs);
+	typioparams = palloc_array(Oid, num_phys_attrs);
+	defmap = palloc_array(int, num_phys_attrs);
+	defexprs = palloc_array(ExprState *, num_phys_attrs);
 
 	for (int attnum = 1; attnum <= num_phys_attrs; attnum++)
 	{
@@ -1842,7 +1842,7 @@ BeginCopyFrom(ParseState *pstate,
 		}
 	}
 
-	cstate->defaults = (bool *) palloc0(tupDesc->natts * sizeof(bool));
+	cstate->defaults = palloc0_array(bool, tupDesc->natts);
 
 	/* initialize progress */
 	pgstat_progress_start_command(PROGRESS_COMMAND_COPY,
diff --git a/src/backend/commands/copyto.c b/src/backend/commands/copyto.c
index b0bdfb58104..5850608a3fb 100644
--- a/src/backend/commands/copyto.c
+++ b/src/backend/commands/copyto.c
@@ -1093,7 +1093,7 @@ BeginCopyTo(ParseState *pstate,
 	num_phys_attrs = tupDesc->natts;
 
 	/* Convert FORCE_QUOTE name list to per-column flags, check validity */
-	cstate->opts.force_quote_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool));
+	cstate->opts.force_quote_flags = palloc0_array(bool, num_phys_attrs);
 	if (cstate->opts.force_quote_all)
 	{
 		MemSet(cstate->opts.force_quote_flags, true, num_phys_attrs * sizeof(bool));
@@ -1283,7 +1283,7 @@ DoCopyTo(CopyToState cstate)
 	cstate->fe_msgbuf = makeStringInfo();
 
 	/* Get info about the columns we need to process. */
-	cstate->out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
+	cstate->out_functions = palloc_array(FmgrInfo, num_phys_attrs);
 	foreach(cur, cstate->attnumlist)
 	{
 		int			attnum = lfirst_int(cur);
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index a32af9894bf..7e3fc59eafd 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -3103,7 +3103,7 @@ remove_dbtablespaces(Oid db_id)
 		return;
 	}
 
-	tablespace_ids = (Oid *) palloc(ntblspc * sizeof(Oid));
+	tablespace_ids = palloc_array(Oid, ntblspc);
 	i = 0;
 	foreach(cell, ltblspc)
 		tablespace_ids[i++] = lfirst_oid(cell);
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index a40d03d35f3..b386e4a13d8 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -5189,10 +5189,9 @@ ExplainCreateWorkersState(int num_workers)
 
 	wstate = palloc_object(ExplainWorkersState);
 	wstate->num_workers = num_workers;
-	wstate->worker_inited = (bool *) palloc0(num_workers * sizeof(bool));
-	wstate->worker_str = (StringInfoData *)
-		palloc0(num_workers * sizeof(StringInfoData));
-	wstate->worker_state_save = (int *) palloc(num_workers * sizeof(int));
+	wstate->worker_inited = palloc0_array(bool, num_workers);
+	wstate->worker_str = palloc0_array(StringInfoData, num_workers);
+	wstate->worker_state_save = palloc_array(int, num_workers);
 	return wstate;
 }
 
diff --git a/src/backend/commands/explain_dr.c b/src/backend/commands/explain_dr.c
index 3c96061cf32..97166f9c06c 100644
--- a/src/backend/commands/explain_dr.c
+++ b/src/backend/commands/explain_dr.c
@@ -63,7 +63,7 @@ serialize_prepare_info(SerializeDestReceiver *receiver,
 	if (nattrs <= 0)
 		return;
 
-	receiver->finfos = (FmgrInfo *) palloc0(nattrs * sizeof(FmgrInfo));
+	receiver->finfos = palloc0_array(FmgrInfo, nattrs);
 
 	for (int i = 0; i < nattrs; i++)
 	{
diff --git a/src/backend/commands/explain_state.c b/src/backend/commands/explain_state.c
index a0ee0a664be..8797a49551a 100644
--- a/src/backend/commands/explain_state.c
+++ b/src/backend/commands/explain_state.c
@@ -295,8 +295,7 @@ SetExplainExtensionState(ExplainState *es, int extension_id, void *opaque)
 	{
 		es->extension_state_allocated =
 			Max(16, pg_nextpower2_32(extension_id + 1));
-		es->extension_state =
-			palloc0(es->extension_state_allocated * sizeof(void *));
+		es->extension_state = palloc0_array(void *, es->extension_state_allocated);
 	}
 
 	/* If there's an array but it's currently full, expand it. */
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index ae03f20c343..03fb01e2cb9 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -645,7 +645,7 @@ get_extension_aux_control_filename(ExtensionControlFile *control,
 
 	scriptdir = get_extension_script_directory(control);
 
-	result = (char *) palloc(MAXPGPATH);
+	result = palloc_array(char, MAXPGPATH);
 	snprintf(result, MAXPGPATH, "%s/%s--%s.control",
 			 scriptdir, control->name, version);
 
@@ -663,7 +663,7 @@ get_extension_script_filename(ExtensionControlFile *control,
 
 	scriptdir = get_extension_script_directory(control);
 
-	result = (char *) palloc(MAXPGPATH);
+	result = palloc_array(char, MAXPGPATH);
 	if (from_version)
 		snprintf(result, MAXPGPATH, "%s/%s--%s--%s.sql",
 				 scriptdir, control->name, from_version, version);
@@ -2751,7 +2751,7 @@ convert_requires_to_datum(List *requires)
 	ListCell   *lc;
 
 	ndatums = list_length(requires);
-	datums = (Datum *) palloc(ndatums * sizeof(Datum));
+	datums = palloc_array(Datum, ndatums);
 	ndatums = 0;
 	foreach(lc, requires)
 	{
@@ -4025,7 +4025,7 @@ read_whole_file(const char *filename, int *length)
 				 errmsg("could not open file \"%s\" for reading: %m",
 						filename)));
 
-	buf = (char *) palloc(bytes_to_read + 1);
+	buf = palloc_array(char, bytes_to_read + 1);
 
 	bytes_to_read = fread(buf, 1, bytes_to_read, file);
 
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 3afd762e9dc..ba24a708982 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -213,10 +213,10 @@ interpret_function_parameter_list(ParseState *pstate,
 	*variadicArgType = InvalidOid;	/* default result */
 	*requiredResultType = InvalidOid;	/* default result */
 
-	inTypes = (Oid *) palloc(parameterCount * sizeof(Oid));
-	allTypes = (Datum *) palloc(parameterCount * sizeof(Datum));
-	paramModes = (Datum *) palloc(parameterCount * sizeof(Datum));
-	paramNames = (Datum *) palloc0(parameterCount * sizeof(Datum));
+	inTypes = palloc_array(Oid, parameterCount);
+	allTypes = palloc_array(Datum, parameterCount);
+	paramModes = palloc_array(Datum, parameterCount);
+	paramNames = palloc0_array(Datum, parameterCount);
 	*parameterDefaults = NIL;
 
 	/* Scan the list and extract data into work arrays */
@@ -918,8 +918,8 @@ interpret_AS_clause(Oid languageOid, const char *languageName,
 
 		pinfo->fname = funcname;
 		pinfo->nargs = list_length(parameterTypes);
-		pinfo->argtypes = (Oid *) palloc(pinfo->nargs * sizeof(Oid));
-		pinfo->argnames = (char **) palloc(pinfo->nargs * sizeof(char *));
+		pinfo->argtypes = palloc_array(Oid, pinfo->nargs);
+		pinfo->argnames = palloc_array(char *, pinfo->nargs);
 		for (int i = 0; i < list_length(parameterTypes); i++)
 		{
 			char	   *s = strVal(list_nth(inParameterNames, i));
@@ -1227,7 +1227,7 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt)
 		Datum	   *arr;
 		int			i;
 
-		arr = palloc(list_length(trftypes_list) * sizeof(Datum));
+		arr = palloc_array(Datum, list_length(trftypes_list));
 		i = 0;
 		foreach(lc, trftypes_list)
 			arr[i++] = ObjectIdGetDatum(lfirst_oid(lc));
diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c
index 4ca086bf4bb..c5c607c7807 100644
--- a/src/backend/commands/policy.c
+++ b/src/backend/commands/policy.c
@@ -163,7 +163,7 @@ policy_role_list_to_array(List *roles, int *num_roles)
 	}
 
 	*num_roles = list_length(roles);
-	role_oids = (Datum *) palloc(*num_roles * sizeof(Datum));
+	role_oids = palloc_array(Datum, *num_roles);
 
 	foreach(cell, roles)
 	{
diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c
index dde56fb1e8d..4c207594678 100644
--- a/src/backend/commands/repack.c
+++ b/src/backend/commands/repack.c
@@ -3781,7 +3781,7 @@ get_initial_snapshot(DecodingWorker *worker)
 	DecodingWorkerFileName(fname, shared->relid, WORKER_FILE_SNAPSHOT);
 	file = BufFileOpenFileSet(&shared->sfs.fs, fname, O_RDONLY, false);
 	BufFileReadExact(file, &snap_size, sizeof(snap_size));
-	snap_space = (char *) palloc(snap_size);
+	snap_space = palloc_array(char, snap_size);
 	BufFileReadExact(file, snap_space, snap_size);
 	BufFileClose(file);
 
diff --git a/src/backend/commands/repack_worker.c b/src/backend/commands/repack_worker.c
index af7e2a94764..f5014cbce0e 100644
--- a/src/backend/commands/repack_worker.c
+++ b/src/backend/commands/repack_worker.c
@@ -315,7 +315,7 @@ export_initial_snapshot(Snapshot snapshot, DecodingWorkerShared *shared)
 	char	   *snap_space;
 
 	snap_size = EstimateSnapshotSpace(snapshot);
-	snap_space = (char *) palloc(snap_size);
+	snap_space = palloc_array(char, snap_size);
 	SerializeSnapshot(snapshot, snap_space);
 
 	DecodingWorkerFileName(fname, shared->relid, shared->last_exported + 1);
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 8e8db08bd93..dd903c21461 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -1169,8 +1169,8 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data,
 		 * allocate separate arrays for table OIDs and sequence OIDs based on
 		 * the total number of relations (subrel_count).
 		 */
-		subrel_local_oids = palloc(subrel_count * sizeof(Oid));
-		subseq_local_oids = palloc(subrel_count * sizeof(Oid));
+		subrel_local_oids = palloc_array(Oid, subrel_count);
+		subseq_local_oids = palloc_array(Oid, subrel_count);
 		foreach(lc, subrel_states)
 		{
 			SubscriptionRelState *relstate = (SubscriptionRelState *) lfirst(lc);
@@ -1202,7 +1202,7 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data,
 		 * step.
 		 */
 		off = 0;
-		pubrel_local_oids = palloc(list_length(pubrels) * sizeof(Oid));
+		pubrel_local_oids = palloc_array(Oid, list_length(pubrels));
 
 		foreach_ptr(PublicationRelKind, pubrelinfo, pubrels)
 		{
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 2fa534413ea..f1a672c4cc4 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -2162,8 +2162,7 @@ ExecuteTruncateGuts(List *explicit_rels,
 	 * ExecGetTriggerResultRel() find them.
 	 */
 	estate = CreateExecutorState();
-	resultRelInfos = (ResultRelInfo *)
-		palloc(list_length(rels) * sizeof(ResultRelInfo));
+	resultRelInfos = palloc_array(ResultRelInfo, list_length(rels));
 	resultRelInfo = resultRelInfos;
 	foreach(cell, rels)
 	{
@@ -2370,7 +2369,7 @@ ExecuteTruncateGuts(List *explicit_rels,
 		/* should only get here if effective_wal_level is 'logical' */
 		Assert(XLogLogicalInfoActive());
 
-		logrelids = palloc(list_length(relids_logged) * sizeof(Oid));
+		logrelids = palloc_array(Oid, list_length(relids_logged));
 		foreach(cell, relids_logged)
 			logrelids[i++] = lfirst_oid(cell);
 
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index d91fcf0facf..e3c4a7fac87 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -1241,7 +1241,7 @@ check_temp_tablespaces(char **newval, void **extra, GucSource source)
 		ListCell   *l;
 
 		/* temporary workspace until we are done verifying the list */
-		tblSpcs = (Oid *) palloc(list_length(namelist) * sizeof(Oid));
+		tblSpcs = palloc_array(Oid, list_length(namelist));
 		numSpcs = 0;
 		foreach(l, namelist)
 		{
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 292c76b1967..1a9c0a658c1 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -911,7 +911,7 @@ CreateTriggerFiringOn(const CreateTrigStmt *stmt, const char *queryString,
 					len++;
 			}
 		}
-		args = (char *) palloc(len + 1);
+		args = palloc_array(char, len + 1);
 		args[0] = '\0';
 		foreach(le, stmt->args)
 		{
@@ -946,7 +946,7 @@ CreateTriggerFiringOn(const CreateTrigStmt *stmt, const char *queryString,
 		ListCell   *cell;
 		int			i = 0;
 
-		columns = (int16 *) palloc(ncolumns * sizeof(int16));
+		columns = palloc_array(int16, ncolumns);
 		foreach(cell, stmt->columns)
 		{
 			char	   *name = strVal(lfirst(cell));
@@ -1903,7 +1903,7 @@ RelationBuildTriggers(Relation relation)
 	 * necessary)
 	 */
 	maxtrigs = 16;
-	triggers = (Trigger *) palloc(maxtrigs * sizeof(Trigger));
+	triggers = palloc_array(Trigger, maxtrigs);
 	numtrigs = 0;
 
 	/*
@@ -1953,7 +1953,7 @@ RelationBuildTriggers(Relation relation)
 		build->tgnattr = pg_trigger->tgattr.dim1;
 		if (build->tgnattr > 0)
 		{
-			build->tgattr = (int16 *) palloc(build->tgnattr * sizeof(int16));
+			build->tgattr = palloc_array(int16, build->tgnattr);
 			memcpy(build->tgattr, &(pg_trigger->tgattr.values),
 				   build->tgnattr * sizeof(int16));
 		}
@@ -1971,7 +1971,7 @@ RelationBuildTriggers(Relation relation)
 				elog(ERROR, "tgargs is null in trigger for relation \"%s\"",
 					 RelationGetRelationName(relation));
 			p = (char *) VARDATA_ANY(val);
-			build->tgargs = (char **) palloc(build->tgnargs * sizeof(char *));
+			build->tgargs = palloc_array(char *, build->tgnargs);
 			for (i = 0; i < build->tgnargs; i++)
 			{
 				build->tgargs[i] = pstrdup(p);
@@ -2126,7 +2126,7 @@ CopyTriggerDesc(TriggerDesc *trigdesc)
 	newdesc = palloc_object(TriggerDesc);
 	memcpy(newdesc, trigdesc, sizeof(TriggerDesc));
 
-	trigger = (Trigger *) palloc(trigdesc->numtriggers * sizeof(Trigger));
+	trigger = palloc_array(Trigger, trigdesc->numtriggers);
 	memcpy(trigger, trigdesc->triggers,
 		   trigdesc->numtriggers * sizeof(Trigger));
 	newdesc->triggers = trigger;
@@ -2138,7 +2138,7 @@ CopyTriggerDesc(TriggerDesc *trigdesc)
 		{
 			int16	   *newattr;
 
-			newattr = (int16 *) palloc(trigger->tgnattr * sizeof(int16));
+			newattr = palloc_array(int16, trigger->tgnattr);
 			memcpy(newattr, trigger->tgattr,
 				   trigger->tgnattr * sizeof(int16));
 			trigger->tgattr = newattr;
@@ -2148,7 +2148,7 @@ CopyTriggerDesc(TriggerDesc *trigdesc)
 			char	  **newargs;
 			int16		j;
 
-			newargs = (char **) palloc(trigger->tgnargs * sizeof(char *));
+			newargs = palloc_array(char *, trigger->tgnargs);
 			for (j = 0; j < trigger->tgnargs; j++)
 				newargs[j] = pstrdup(trigger->tgargs[j]);
 			trigger->tgargs = newargs;
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index a12ce33bae4..1d1d11744d8 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -1641,7 +1641,7 @@ deserialize_deflist(Datum txt)
 	} ds_state;
 	ds_state	state = CS_WAITKEY;
 
-	workspace = (char *) palloc(len + 1);	/* certainly enough room */
+	workspace = palloc_array(char, len + 1);	/* certainly enough room */
 	ptr = VARDATA_ANY(in);
 	endptr = ptr + len;
 	for (; ptr < endptr; ptr++)
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 31f9824899c..6024bf2df31 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -2405,7 +2405,7 @@ vac_open_indexes(Relation relation, LOCKMODE lockmode,
 	i = list_length(indexoidlist);
 
 	if (i > 0)
-		*Irel = (Relation *) palloc(i * sizeof(Relation));
+		*Irel = palloc_array(Relation, i);
 	else
 		*Irel = NULL;
 
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index cfea7e160c2..1322a97cc36 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -1745,7 +1745,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				ExprEvalRowtypeCache *rowcachep;
 
 				/* cache structs must be out-of-line for space reasons */
-				rowcachep = palloc(2 * sizeof(ExprEvalRowtypeCache));
+				rowcachep = palloc_array(ExprEvalRowtypeCache, 2);
 				rowcachep[0].cacheptr = NULL;
 				rowcachep[1].cacheptr = NULL;
 
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 9bc23cb16fa..397219f7a3a 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -3457,10 +3457,10 @@ ExecEvalArrayExpr(ExprState *state, ExprEvalStep *op)
 		char	   *dat;
 		int			iitem;
 
-		subdata = (char **) palloc(nelems * sizeof(char *));
-		subbitmaps = (uint8 **) palloc(nelems * sizeof(uint8 *));
-		subbytes = (int *) palloc(nelems * sizeof(int));
-		subnitems = (int *) palloc(nelems * sizeof(int));
+		subdata = palloc_array(char *, nelems);
+		subbitmaps = palloc_array(uint8 *, nelems);
+		subbytes = palloc_array(int, nelems);
+		subnitems = palloc_array(int, nelems);
 
 		/* loop through and get data area from each element */
 		for (int elemoff = 0; elemoff < nelems; elemoff++)
@@ -3511,9 +3511,9 @@ ExecEvalArrayExpr(ExprState *state, ExprEvalStep *op)
 							 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
 									ndims, MAXDIM)));
 
-				elem_dims = (int *) palloc(elem_ndims * sizeof(int));
+				elem_dims = palloc_array(int, elem_ndims);
 				memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int));
-				elem_lbs = (int *) palloc(elem_ndims * sizeof(int));
+				elem_lbs = palloc_array(int, elem_ndims);
 				memcpy(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int));
 
 				firstone = false;
diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index c107514a85d..feee88294aa 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -72,7 +72,7 @@ execTuplesMatchPrepare(TupleDesc desc,
 	if (numCols == 0)
 		return NULL;
 
-	eqFunctions = (Oid *) palloc(numCols * sizeof(Oid));
+	eqFunctions = palloc_array(Oid, numCols);
 
 	/* lookup equality functions */
 	for (i = 0; i < numCols; i++)
@@ -104,8 +104,8 @@ execTuplesHashPrepare(int numCols,
 {
 	int			i;
 
-	*eqFuncOids = (Oid *) palloc(numCols * sizeof(Oid));
-	*hashFunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo));
+	*eqFuncOids = palloc_array(Oid, numCols);
+	*hashFunctions = palloc_array(FmgrInfo, numCols);
 
 	for (i = 0; i < numCols; i++)
 	{
diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c
index 3736bea3b3c..02494e1f20d 100644
--- a/src/backend/executor/execJunk.c
+++ b/src/backend/executor/execJunk.c
@@ -93,7 +93,7 @@ ExecInitJunkFilter(List *targetList, TupleTableSlot *slot)
 		AttrNumber	cleanResno;
 		ListCell   *t;
 
-		cleanMap = (AttrNumber *) palloc(cleanLength * sizeof(AttrNumber));
+		cleanMap = palloc_array(AttrNumber, cleanLength);
 		cleanResno = 0;
 		foreach(t, targetList)
 		{
@@ -165,7 +165,7 @@ ExecInitJunkFilterConversion(List *targetList,
 	cleanLength = cleanTupType->natts;
 	if (cleanLength > 0)
 	{
-		cleanMap = (AttrNumber *) palloc0(cleanLength * sizeof(AttrNumber));
+		cleanMap = palloc0_array(AttrNumber, cleanLength);
 		t = list_head(targetList);
 		for (i = 0; i < cleanLength; i++)
 		{
diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c
index 81b87d82fab..6b85508a696 100644
--- a/src/backend/executor/execParallel.c
+++ b/src/backend/executor/execParallel.c
@@ -609,8 +609,7 @@ ExecParallelSetupTupleQueues(ParallelContext *pcxt, bool reinitialize)
 		return NULL;
 
 	/* Allocate memory for shared memory queue handles. */
-	responseq = (shm_mq_handle **)
-		palloc(pcxt->nworkers * sizeof(shm_mq_handle *));
+	responseq = palloc_array(shm_mq_handle *, pcxt->nworkers);
 
 	/*
 	 * If not reinitializing, allocate space from the DSM for the queues;
@@ -950,8 +949,7 @@ ExecParallelCreateReaders(ParallelExecutorInfo *pei)
 
 	if (nworkers > 0)
 	{
-		pei->reader = (TupleQueueReader **)
-			palloc(nworkers * sizeof(TupleQueueReader *));
+		pei->reader = palloc_array(TupleQueueReader *, nworkers);
 
 		for (i = 0; i < nworkers; i++)
 		{
diff --git a/src/backend/executor/execSRF.c b/src/backend/executor/execSRF.c
index 8aedcc6a459..f839f3bbde7 100644
--- a/src/backend/executor/execSRF.c
+++ b/src/backend/executor/execSRF.c
@@ -339,7 +339,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
 					int			natts = expectedDesc->natts;
 					bool	   *nullflags;
 
-					nullflags = (bool *) palloc(natts * sizeof(bool));
+					nullflags = palloc_array(bool, natts);
 					memset(nullflags, true, natts * sizeof(bool));
 					tuplestore_putvalues(tupstore, expectedDesc, NULL, nullflags);
 				}
@@ -407,7 +407,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
 			int			natts = expectedDesc->natts;
 			bool	   *nullflags;
 
-			nullflags = (bool *) palloc(natts * sizeof(bool));
+			nullflags = palloc_array(bool, natts);
 			memset(nullflags, true, natts * sizeof(bool));
 			tuplestore_putvalues(tupstore, expectedDesc, NULL, nullflags);
 		}
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 3ad983c7fa5..b8e8f52c64c 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -2389,9 +2389,9 @@ TupleDescGetAttInMetadata(TupleDesc tupdesc)
 	/*
 	 * Gather info needed later to call the "in" function for each attribute
 	 */
-	attinfuncinfo = (FmgrInfo *) palloc0(natts * sizeof(FmgrInfo));
-	attioparams = (Oid *) palloc0(natts * sizeof(Oid));
-	atttypmods = (int32 *) palloc0(natts * sizeof(int32));
+	attinfuncinfo = palloc0_array(FmgrInfo, natts);
+	attioparams = palloc0_array(Oid, natts);
+	atttypmods = palloc0_array(int32, natts);
 
 	for (i = 0; i < natts; i++)
 	{
@@ -2428,8 +2428,8 @@ BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
 	int			i;
 	HeapTuple	tuple;
 
-	dvalues = (Datum *) palloc(natts * sizeof(Datum));
-	nulls = (bool *) palloc(natts * sizeof(bool));
+	dvalues = palloc_array(Datum, natts);
+	nulls = palloc_array(bool, natts);
 
 	/*
 	 * Call the "in" function for each non-dropped attribute, even for nulls,
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 1eb6b9f1f40..c0c4276acbf 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -822,8 +822,7 @@ ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos,
 	 * rangetable entry, and initialize entries to NULL.  Relations are opened
 	 * and stored here as needed.
 	 */
-	estate->es_relations = (Relation *)
-		palloc0(estate->es_range_table_size * sizeof(Relation));
+	estate->es_relations = palloc0_array(Relation, estate->es_range_table_size);
 
 	/*
 	 * es_result_relations and es_rowmarks are also parallel to
@@ -916,8 +915,8 @@ ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo,
 					  estate->es_instrument);
 
 	if (estate->es_result_relations == NULL)
-		estate->es_result_relations = (ResultRelInfo **)
-			palloc0(estate->es_range_table_size * sizeof(ResultRelInfo *));
+		estate->es_result_relations = palloc0_array(ResultRelInfo *,
+													estate->es_range_table_size);
 	estate->es_result_relations[rti - 1] = resultRelInfo;
 
 	/*
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 88109348817..8fec79a2f76 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -275,7 +275,7 @@ prepare_sql_fn_parse_info(HeapTuple procedureTuple,
 		Oid		   *argOidVect;
 		int			argnum;
 
-		argOidVect = (Oid *) palloc(nargs * sizeof(Oid));
+		argOidVect = palloc_array(Oid, nargs);
 		memcpy(argOidVect,
 			   procedureStruct->proargtypes.values,
 			   nargs * sizeof(Oid));
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 925caadd2ce..962cd9c8255 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -1633,10 +1633,8 @@ find_hash_columns(AggState *aggstate)
 		 */
 		maxCols = bms_num_members(colnos) + perhash->numCols;
 
-		perhash->hashGrpColIdxInput =
-			palloc(maxCols * sizeof(AttrNumber));
-		perhash->hashGrpColIdxHash =
-			palloc(perhash->numCols * sizeof(AttrNumber));
+		perhash->hashGrpColIdxInput = palloc_array(AttrNumber, maxCols);
+		perhash->hashGrpColIdxHash = palloc_array(AttrNumber, perhash->numCols);
 
 		/* Add all the grouping columns to colnos */
 		for (i = 0; i < perhash->numCols; i++)
@@ -3560,8 +3558,8 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 
 			if (num_sets)
 			{
-				phasedata->gset_lengths = palloc(num_sets * sizeof(int));
-				phasedata->grouped_cols = palloc(num_sets * sizeof(Bitmapset *));
+				phasedata->gset_lengths = palloc_array(int, num_sets);
+				phasedata->grouped_cols = palloc_array(Bitmapset *, num_sets);
 
 				i = 0;
 				foreach(l, aggnode->groupingSets)
@@ -4318,14 +4316,10 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
 		}
 
 		/* Extract the sort information for use later */
-		pertrans->sortColIdx =
-			(AttrNumber *) palloc(numSortCols * sizeof(AttrNumber));
-		pertrans->sortOperators =
-			(Oid *) palloc(numSortCols * sizeof(Oid));
-		pertrans->sortCollations =
-			(Oid *) palloc(numSortCols * sizeof(Oid));
-		pertrans->sortNullsFirst =
-			(bool *) palloc(numSortCols * sizeof(bool));
+		pertrans->sortColIdx = palloc_array(AttrNumber, numSortCols);
+		pertrans->sortOperators = palloc_array(Oid, numSortCols);
+		pertrans->sortCollations = palloc_array(Oid, numSortCols);
+		pertrans->sortNullsFirst = palloc_array(bool, numSortCols);
 
 		i = 0;
 		foreach(lc, sortlist)
@@ -4352,7 +4346,7 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
 		Assert(numArguments > 0);
 		Assert(list_length(aggref->aggdistinct) == numDistinctCols);
 
-		ops = palloc(numDistinctCols * sizeof(Oid));
+		ops = palloc_array(Oid, numDistinctCols);
 
 		i = 0;
 		foreach(lc, aggref->aggdistinct)
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c
index 51654b31ad1..06f46fe6501 100644
--- a/src/backend/executor/nodeAppend.c
+++ b/src/backend/executor/nodeAppend.c
@@ -182,8 +182,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
 		appendstate->as_prune_state = NULL;
 	}
 
-	appendplanstates = (PlanState **) palloc(nplans *
-											 sizeof(PlanState *));
+	appendplanstates = palloc_array(PlanState *, nplans);
 
 	/*
 	 * call ExecInitNode on each of the valid plans to be executed and save
@@ -259,8 +258,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
 
 	if (nasyncplans > 0)
 	{
-		appendstate->as_asyncrequests = (AsyncRequest **)
-			palloc0(nplans * sizeof(AsyncRequest *));
+		appendstate->as_asyncrequests = palloc0_array(AsyncRequest *, nplans);
 
 		i = -1;
 		while ((i = bms_next_member(asyncplans, i)) >= 0)
@@ -278,8 +276,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
 			appendstate->as_asyncrequests[i] = areq;
 		}
 
-		appendstate->as_asyncresults = (TupleTableSlot **)
-			palloc0(nasyncplans * sizeof(TupleTableSlot *));
+		appendstate->as_asyncresults = palloc0_array(TupleTableSlot *, nasyncplans);
 
 		if (appendstate->as_valid_subplans_identified)
 			classify_matching_subplans(appendstate);
diff --git a/src/backend/executor/nodeBitmapAnd.c b/src/backend/executor/nodeBitmapAnd.c
index 64092fa8065..36ad0a7f85c 100644
--- a/src/backend/executor/nodeBitmapAnd.c
+++ b/src/backend/executor/nodeBitmapAnd.c
@@ -72,7 +72,7 @@ ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
 	 */
 	nplans = list_length(node->bitmapplans);
 
-	bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
+	bitmapplanstates = palloc0_array(PlanState *, nplans);
 
 	/*
 	 * create new BitmapAndState for our BitmapAnd node
diff --git a/src/backend/executor/nodeBitmapOr.c b/src/backend/executor/nodeBitmapOr.c
index b98b96172fe..e84f97eebd4 100644
--- a/src/backend/executor/nodeBitmapOr.c
+++ b/src/backend/executor/nodeBitmapOr.c
@@ -73,7 +73,7 @@ ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
 	 */
 	nplans = list_length(node->bitmapplans);
 
-	bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
+	bitmapplanstates = palloc0_array(PlanState *, nplans);
 
 	/*
 	 * create new BitmapOrState for our BitmapOr node
diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c
index 114693abb32..31cd95adee7 100644
--- a/src/backend/executor/nodeGather.c
+++ b/src/backend/executor/nodeGather.c
@@ -196,8 +196,7 @@ ExecGather(PlanState *pstate)
 				ExecParallelCreateReaders(node->pei);
 				/* Make a working array showing the active readers */
 				node->nreaders = pcxt->nworkers_launched;
-				node->reader = (TupleQueueReader **)
-					palloc(node->nreaders * sizeof(TupleQueueReader *));
+				node->reader = palloc_array(TupleQueueReader *, node->nreaders);
 				memcpy(node->reader, node->pei->reader,
 					   node->nreaders * sizeof(TupleQueueReader *));
 			}
diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c
index c2ac5e0792c..352a89ab53f 100644
--- a/src/backend/executor/nodeGatherMerge.c
+++ b/src/backend/executor/nodeGatherMerge.c
@@ -237,8 +237,7 @@ ExecGatherMerge(PlanState *pstate)
 				ExecParallelCreateReaders(node->pei);
 				/* Make a working array showing the active readers */
 				node->nreaders = pcxt->nworkers_launched;
-				node->reader = (TupleQueueReader **)
-					palloc(node->nreaders * sizeof(TupleQueueReader *));
+				node->reader = palloc_array(TupleQueueReader *, node->nreaders);
 				memcpy(node->reader, node->pei->reader,
 					   node->nreaders * sizeof(TupleQueueReader *));
 			}
@@ -408,12 +407,10 @@ gather_merge_setup(GatherMergeState *gm_state)
 	 * scan, we might have fewer than num_workers available workers, in which
 	 * case the extra array entries go unused.
 	 */
-	gm_state->gm_slots = (TupleTableSlot **)
-		palloc0((nreaders + 1) * sizeof(TupleTableSlot *));
+	gm_state->gm_slots = palloc0_array(TupleTableSlot *, nreaders + 1);
 
 	/* Allocate the tuple slot and tuple array for each worker */
-	gm_state->gm_tuple_buffers = (GMReaderTupleBuffer *)
-		palloc0(nreaders * sizeof(GMReaderTupleBuffer));
+	gm_state->gm_tuple_buffers = palloc0_array(GMReaderTupleBuffer, nreaders);
 
 	for (i = 0; i < nreaders; i++)
 	{
diff --git a/src/backend/executor/nodeIncrementalSort.c b/src/backend/executor/nodeIncrementalSort.c
index 1d831049b65..f2e92d7cf0b 100644
--- a/src/backend/executor/nodeIncrementalSort.c
+++ b/src/backend/executor/nodeIncrementalSort.c
@@ -165,9 +165,7 @@ preparePresortedCols(IncrementalSortState *node)
 {
 	IncrementalSort *plannode = castNode(IncrementalSort, node->ss.ps.plan);
 
-	node->presorted_keys =
-		(PresortedKeyData *) palloc(plannode->nPresortedCols *
-									sizeof(PresortedKeyData));
+	node->presorted_keys = palloc_array(PresortedKeyData, plannode->nPresortedCols);
 
 	/* Pre-cache comparison functions for each pre-sorted key. */
 	for (int i = 0; i < plannode->nPresortedCols; i++)
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 39f6691ee35..8143fcf2581 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -1035,12 +1035,9 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
 		 */
 		Assert(numOrderByKeys == list_length(node->indexorderbyops));
 		Assert(numOrderByKeys == list_length(node->indexorderbyorig));
-		indexstate->iss_SortSupport = (SortSupportData *)
-			palloc0(numOrderByKeys * sizeof(SortSupportData));
-		indexstate->iss_OrderByTypByVals = (bool *)
-			palloc(numOrderByKeys * sizeof(bool));
-		indexstate->iss_OrderByTypLens = (int16 *)
-			palloc(numOrderByKeys * sizeof(int16));
+		indexstate->iss_SortSupport = palloc0_array(SortSupportData, numOrderByKeys);
+		indexstate->iss_OrderByTypByVals = palloc_array(bool, numOrderByKeys);
+		indexstate->iss_OrderByTypLens = palloc_array(int16, numOrderByKeys);
 		i = 0;
 		forboth(lco, node->indexorderbyops, lcx, node->indexorderbyorig)
 		{
@@ -1068,10 +1065,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
 		}
 
 		/* allocate arrays to hold the re-calculated distances */
-		indexstate->iss_OrderByValues = (Datum *)
-			palloc(numOrderByKeys * sizeof(Datum));
-		indexstate->iss_OrderByNulls = (bool *)
-			palloc(numOrderByKeys * sizeof(bool));
+		indexstate->iss_OrderByValues = palloc_array(Datum, numOrderByKeys);
+		indexstate->iss_OrderByNulls = palloc_array(bool, numOrderByKeys);
 
 		/* and initialize the reorder queue */
 		indexstate->iss_ReorderQueue = pairingheap_allocate(reorderqueue_cmp,
@@ -1182,7 +1177,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 
 	/* Allocate array for ScanKey structs: one per qual */
 	n_scan_keys = list_length(quals);
-	scan_keys = (ScanKey) palloc(n_scan_keys * sizeof(ScanKeyData));
+	scan_keys = palloc_array(ScanKeyData, n_scan_keys);
 
 	/*
 	 * runtime_keys array is dynamically resized as needed.  We handle it this
@@ -1195,8 +1190,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 	n_runtime_keys = max_runtime_keys = *numRuntimeKeys;
 
 	/* Allocate array_keys as large as it could possibly need to be */
-	array_keys = (IndexArrayKeyInfo *)
-		palloc0(n_scan_keys * sizeof(IndexArrayKeyInfo));
+	array_keys = palloc0_array(IndexArrayKeyInfo, n_scan_keys);
 	n_array_keys = 0;
 
 	/*
@@ -1286,8 +1280,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 					if (max_runtime_keys == 0)
 					{
 						max_runtime_keys = 8;
-						runtime_keys = (IndexRuntimeKeyInfo *)
-							palloc(max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
+						runtime_keys = palloc_array(IndexRuntimeKeyInfo, max_runtime_keys);
 					}
 					else
 					{
@@ -1330,8 +1323,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 
 			Assert(!isorderby);
 
-			first_sub_key = (ScanKey)
-				palloc(list_length(rc->opnos) * sizeof(ScanKeyData));
+			first_sub_key = (ScanKey) palloc_array(ScanKeyData, list_length(rc->opnos));
 			n_sub_key = 0;
 
 			/* Scan RowCompare columns and generate subsidiary ScanKey items */
@@ -1410,8 +1402,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 						if (max_runtime_keys == 0)
 						{
 							max_runtime_keys = 8;
-							runtime_keys = (IndexRuntimeKeyInfo *)
-								palloc(max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
+							runtime_keys = palloc_array(IndexRuntimeKeyInfo, max_runtime_keys);
 						}
 						else
 						{
diff --git a/src/backend/executor/nodeMemoize.c b/src/backend/executor/nodeMemoize.c
index fdca97d7426..49330168a75 100644
--- a/src/backend/executor/nodeMemoize.c
+++ b/src/backend/executor/nodeMemoize.c
@@ -1001,12 +1001,12 @@ ExecInitMemoize(Memoize *node, EState *estate, int eflags)
 	mstate->probeslot = MakeSingleTupleTableSlot(mstate->hashkeydesc,
 												 &TTSOpsVirtual);
 
-	mstate->param_exprs = (ExprState **) palloc(nkeys * sizeof(ExprState *));
+	mstate->param_exprs = palloc_array(ExprState *, nkeys);
 	mstate->collations = node->collations;	/* Just point directly to the plan
 											 * data */
-	mstate->hashfunctions = (FmgrInfo *) palloc(nkeys * sizeof(FmgrInfo));
+	mstate->hashfunctions = palloc_array(FmgrInfo, nkeys);
 
-	eqfuncoids = palloc(nkeys * sizeof(Oid));
+	eqfuncoids = palloc_array(Oid, nkeys);
 
 	for (i = 0; i < nkeys; i++)
 	{
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index f8421a74c75..8ab35f2e8f8 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -186,7 +186,7 @@ MJExamineQuals(List *mergeclauses,
 	int			iClause;
 	ListCell   *cl;
 
-	clauses = (MergeJoinClause) palloc0(nClauses * sizeof(MergeJoinClauseData));
+	clauses = (MergeJoinClause) palloc0_array(MergeJoinClauseData, nClauses);
 
 	iClause = 0;
 	foreach(cl, mergeclauses)
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 9a1c0992bfe..ca954729f1e 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -485,7 +485,7 @@ ExecInitGenerated(ResultRelInfo *resultRelInfo,
 	 */
 	oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
 
-	ri_GeneratedExprs = (ExprState **) palloc0(natts * sizeof(ExprState *));
+	ri_GeneratedExprs = palloc0_array(ExprState *, natts);
 	ri_NumGeneratedNeeded = 0;
 
 	for (int i = 0; i < natts; i++)
diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c
index 24709778384..079591aed24 100644
--- a/src/backend/executor/nodeSetOp.c
+++ b/src/backend/executor/nodeSetOp.c
@@ -654,8 +654,7 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags)
 	{
 		int			nkeys = node->numCols;
 
-		setopstate->sortKeys = (SortSupport)
-			palloc0(nkeys * sizeof(SortSupportData));
+		setopstate->sortKeys = (SortSupport) palloc0_array(SortSupportData, nkeys);
 		for (int i = 0; i < nkeys; i++)
 		{
 			SortSupport sortKey = setopstate->sortKeys + i;
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 8285c7101c2..c6dd463c118 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -974,14 +974,14 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
 
 		lefttlist = righttlist = NIL;
 		sstate->numCols = ncols;
-		sstate->keyColIdx = (AttrNumber *) palloc(ncols * sizeof(AttrNumber));
-		sstate->tab_eq_funcoids = (Oid *) palloc(ncols * sizeof(Oid));
-		sstate->tab_collations = (Oid *) palloc(ncols * sizeof(Oid));
-		sstate->tab_hash_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));
-		lhs_hash_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));
-		sstate->cur_eq_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));
+		sstate->keyColIdx = palloc_array(AttrNumber, ncols);
+		sstate->tab_eq_funcoids = palloc_array(Oid, ncols);
+		sstate->tab_collations = palloc_array(Oid, ncols);
+		sstate->tab_hash_funcs = palloc_array(FmgrInfo, ncols);
+		lhs_hash_funcs = palloc_array(FmgrInfo, ncols);
+		sstate->cur_eq_funcs = palloc_array(FmgrInfo, ncols);
 		/* we'll need the cross-type equality fns below, but not in sstate */
-		cross_eq_funcoids = (Oid *) palloc(ncols * sizeof(Oid));
+		cross_eq_funcoids = palloc_array(Oid, ncols);
 
 		i = 1;
 		foreach(l, oplist)
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index 6641df10999..19e55b85f64 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -157,8 +157,7 @@ TidListEval(TidScanState *tidstate)
 	 * ScalarArrayOpExprs, we may have to enlarge the array.
 	 */
 	numAllocTids = list_length(tidstate->tss_tidexprs);
-	tidList = (ItemPointerData *)
-		palloc(numAllocTids * sizeof(ItemPointerData));
+	tidList = palloc_array(ItemPointerData, numAllocTids);
 	numTids = 0;
 
 	foreach(l, tidstate->tss_tidexprs)
diff --git a/src/backend/executor/nodeValuesscan.c b/src/backend/executor/nodeValuesscan.c
index effc896ea1c..51c32979481 100644
--- a/src/backend/executor/nodeValuesscan.c
+++ b/src/backend/executor/nodeValuesscan.c
@@ -277,10 +277,8 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
 	 * and/or leaked resources if we try to handle SubPlans the same as
 	 * simpler expressions.)
 	 */
-	scanstate->exprlists = (List **)
-		palloc(scanstate->array_len * sizeof(List *));
-	scanstate->exprstatelists = (List **)
-		palloc0(scanstate->array_len * sizeof(List *));
+	scanstate->exprlists = palloc_array(List *, scanstate->array_len);
+	scanstate->exprstatelists = palloc0_array(List *, scanstate->array_len);
 	i = 0;
 	foreach(vtl, node->values_lists)
 	{
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 7d6ec2dfc4b..2e36c49580e 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -3563,13 +3563,13 @@ grow_notnull_info(WindowObject winobj, int64 pos, int argno)
 								 * arg */
 			{
 				newsize = NN_POS_TO_BYTES(INIT_NOT_NULL_INFO_NUM);
-				winobj->notnull_info[argno] = palloc0(newsize);
+				winobj->notnull_info[argno] = palloc0_array(uint8, newsize);
 			}
 			else
 			{
 				newsize = oldsize * 2;
 				winobj->notnull_info[argno] =
-					repalloc0(winobj->notnull_info[argno], oldsize, newsize);
+					repalloc0_array(winobj->notnull_info[argno], uint8, oldsize, newsize);
 			}
 			winobj->num_notnull_info[argno] = NN_BYTES_TO_POS(newsize);
 			if (winobj->num_notnull_info[argno] > pos)
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index 29617437477..09a52a18921 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -700,8 +700,7 @@ llvm_compile_expr(ExprState *state)
 						LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
 
 						/* create blocks for checking args, one for each */
-						b_checkargnulls = (LLVMBasicBlockRef *)
-							palloc(sizeof(LLVMBasicBlockRef) * op->d.func.nargs);
+						b_checkargnulls = palloc_array(LLVMBasicBlockRef, op->d.func.nargs);
 						for (int argno = 0; argno < op->d.func.nargs; argno++)
 							b_checkargnulls[argno] =
 								l_bb_before_v(b_nonull, "b.%d.isnull.%d", opno,
diff --git a/src/backend/lib/bipartite_match.c b/src/backend/lib/bipartite_match.c
index 12520dc91b4..cf470275f48 100644
--- a/src/backend/lib/bipartite_match.c
+++ b/src/backend/lib/bipartite_match.c
@@ -48,10 +48,10 @@ BipartiteMatch(int u_size, int v_size, short **adjacency)
 	state->v_size = v_size;
 	state->adjacency = adjacency;
 	state->matching = 0;
-	state->pair_uv = (short *) palloc0((u_size + 1) * sizeof(short));
-	state->pair_vu = (short *) palloc0((v_size + 1) * sizeof(short));
-	state->distance = (short *) palloc((u_size + 1) * sizeof(short));
-	state->queue = (short *) palloc((u_size + 2) * sizeof(short));
+	state->pair_uv = palloc0_array(short, u_size + 1);
+	state->pair_vu = palloc0_array(short, v_size + 1);
+	state->distance = palloc_array(short, u_size + 1);
+	state->queue = palloc_array(short, u_size + 2);
 
 	while (hk_breadth_search(state))
 	{
diff --git a/src/backend/lib/knapsack.c b/src/backend/lib/knapsack.c
index 586f1881fd5..23743f233ac 100644
--- a/src/backend/lib/knapsack.c
+++ b/src/backend/lib/knapsack.c
@@ -64,8 +64,8 @@ DiscreteKnapsack(int max_weight, int num_items,
 	Assert(max_weight >= 0);
 	Assert(num_items > 0 && item_weights);
 
-	values = palloc((1 + max_weight) * sizeof(double));
-	sets = palloc((1 + max_weight) * sizeof(Bitmapset *));
+	values = palloc_array(double, 1 + max_weight);
+	sets = palloc_array(Bitmapset *, 1 + max_weight);
 
 	for (i = 0; i <= max_weight; ++i)
 	{
diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c
index 4bac15fc5c1..77450c7060b 100644
--- a/src/backend/libpq/auth-scram.c
+++ b/src/backend/libpq/auth-scram.c
@@ -718,7 +718,7 @@ mock_scram_secret(const char *username, pg_cryptohash_type *hash_type,
 
 	encoded_len = pg_b64_enc_len(SCRAM_DEFAULT_SALT_LEN);
 	/* don't forget the zero-terminator */
-	encoded_salt = (char *) palloc(encoded_len + 1);
+	encoded_salt = palloc_array(char, encoded_len + 1);
 	encoded_len = pg_b64_encode(raw_salt, SCRAM_DEFAULT_SALT_LEN, encoded_salt,
 								encoded_len);
 
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index d47eab2cba0..c0d8a9d8a00 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -309,7 +309,7 @@ regcomp_auth_token(AuthToken *token, char *filename, int line_num,
 		return 0;				/* nothing to compile */
 
 	token->regex = palloc0_object(regex_t);
-	wstr = palloc((strlen(token->string + 1) + 1) * sizeof(pg_wchar));
+	wstr = palloc_array(pg_wchar, strlen(token->string + 1) + 1);
 	wlen = pg_mb2wchar_with_len(token->string + 1,
 								wstr, strlen(token->string + 1));
 
@@ -350,7 +350,7 @@ regexec_auth_token(const char *match, AuthToken *token, size_t nmatch,
 
 	Assert(token->string[0] == '/' && token->regex);
 
-	wmatchstr = palloc((strlen(match) + 1) * sizeof(pg_wchar));
+	wmatchstr = palloc_array(pg_wchar, strlen(match) + 1);
 	wmatchlen = pg_mb2wchar_with_len(match, wmatchstr, strlen(match));
 
 	r = pg_regexec(token->regex, wmatchstr, wmatchlen, 0, NULL, nmatch, pmatch, 0);
diff --git a/src/backend/libpq/pqformat.c b/src/backend/libpq/pqformat.c
index 8b41aa4f1cb..d02eb51bcd5 100644
--- a/src/backend/libpq/pqformat.c
+++ b/src/backend/libpq/pqformat.c
@@ -559,7 +559,7 @@ pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
 		*nbytes = strlen(p);
 	else
 	{
-		p = (char *) palloc(rawbytes + 1);
+		p = palloc_array(char, rawbytes + 1);
 		memcpy(p, str, rawbytes);
 		p[rawbytes] = '\0';
 		*nbytes = rawbytes;
diff --git a/src/backend/nodes/queryjumblefuncs.c b/src/backend/nodes/queryjumblefuncs.c
index 2ce27b9e552..15cf9862cf7 100644
--- a/src/backend/nodes/queryjumblefuncs.c
+++ b/src/backend/nodes/queryjumblefuncs.c
@@ -186,11 +186,10 @@ InitJumble(void)
 	jstate = palloc_object(JumbleState);
 
 	/* Set up workspace for query jumbling */
-	jstate->jumble = (unsigned char *) palloc(JUMBLE_SIZE);
+	jstate->jumble = palloc_array(unsigned char, JUMBLE_SIZE);
 	jstate->jumble_len = 0;
 	jstate->clocations_buf_size = 32;
-	jstate->clocations = (LocationLen *) palloc(jstate->clocations_buf_size *
-												sizeof(LocationLen));
+	jstate->clocations = palloc_array(LocationLen, jstate->clocations_buf_size);
 	jstate->clocations_count = 0;
 	jstate->highest_extern_param_id = 0;
 	jstate->pending_nulls = 0;
diff --git a/src/backend/nodes/read.c b/src/backend/nodes/read.c
index f85cf65ea48..35576d2c385 100644
--- a/src/backend/nodes/read.c
+++ b/src/backend/nodes/read.c
@@ -483,7 +483,7 @@ nodeRead(const char *token, int tok_len)
 			break;
 		case T_Float:
 			{
-				char	   *fval = (char *) palloc(tok_len + 1);
+				char	   *fval = palloc_array(char, tok_len + 1);
 
 				memcpy(fval, token, tok_len);
 				fval[tok_len] = '\0';
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index b6b2ce6c792..5b3dc798c82 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -639,7 +639,7 @@ readDatum(bool typbyval)
 		res = (Datum) 0;
 	else
 	{
-		s = (char *) palloc(length);
+		s = palloc_array(char, length);
 		for (Size i = 0; i < length; i++)
 		{
 			token = pg_strtok(&tokenLength);
@@ -677,7 +677,7 @@ fnname(int numCols) \
 		return NULL;			/* it was "<>", so return NULL pointer */ \
 	if (length != 1 || token[0] != '(') \
 		elog(ERROR, "unrecognized token: \"%.*s\"", length, token); \
-	vals = (datatype *) palloc(numCols * sizeof(datatype)); \
+	vals = palloc_array(datatype, numCols); \
 	for (int i = 0; i < numCols; i++) \
 	{ \
 		token = pg_strtok(&length); \
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 9c040ecefc8..24a6a8d11dd 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -1079,7 +1079,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
 	parent_rows = 0;
 	parent_size = 0;
 	nattrs = rel->max_attr - rel->min_attr + 1;
-	parent_attrsizes = (double *) palloc0(nattrs * sizeof(double));
+	parent_attrsizes = palloc0_array(double, nattrs);
 
 	foreach(l, root->append_rel_list)
 	{
@@ -2717,8 +2717,8 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
 	 * a pushed-down qual.
 	 */
 	memset(&safetyInfo, 0, sizeof(safetyInfo));
-	safetyInfo.unsafeFlags = (unsigned char *)
-		palloc0((list_length(subquery->targetList) + 1) * sizeof(unsigned char));
+	safetyInfo.unsafeFlags = palloc0_array(unsigned char,
+										   list_length(subquery->targetList) + 1);
 
 	/*
 	 * If the subquery has the "security_barrier" flag, it means the subquery
@@ -3971,7 +3971,7 @@ standard_join_search(PlannerInfo *root, int levels_needed, List *initial_rels)
 	 * set root->join_rel_level[1] to represent all the single-jointree-item
 	 * relations.
 	 */
-	root->join_rel_level = (List **) palloc0((levels_needed + 1) * sizeof(List *));
+	root->join_rel_level = palloc0_array(List *, levels_needed + 1);
 
 	root->join_rel_level[1] = initial_rels;
 
diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c
index e3697df51a2..0dcc2ed4266 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -1381,8 +1381,7 @@ generate_base_implied_equalities_no_const(PlannerInfo *root,
 	 * ordering would succeed.  XXX FIXME: use a UNION-FIND algorithm similar
 	 * to the way we build merged ECs.  (Use a list-of-lists for each rel.)
 	 */
-	prev_ems = (EquivalenceMember **)
-		palloc0(root->simple_rel_array_size * sizeof(EquivalenceMember *));
+	prev_ems = palloc0_array(EquivalenceMember *, root->simple_rel_array_size);
 
 	/* We don't expect any children yet */
 	Assert(ec->ec_childmembers == NULL);
diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c
index 5eb71635d15..d6a305aedac 100644
--- a/src/backend/optimizer/path/pathkeys.c
+++ b/src/backend/optimizer/path/pathkeys.c
@@ -1676,8 +1676,8 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
 	 * Make arrays of the ECs used by the mergeclauses (dropping any
 	 * duplicates) and their "popularity" scores.
 	 */
-	ecs = (EquivalenceClass **) palloc(nClauses * sizeof(EquivalenceClass *));
-	scores = (int *) palloc(nClauses * sizeof(int));
+	ecs = palloc_array(EquivalenceClass *, nClauses);
+	scores = palloc_array(int, nClauses);
 	necs = 0;
 
 	foreach(lc, mergeclauses)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index ab392ef60fe..f7841f979a0 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -1736,8 +1736,8 @@ create_memoize_plan(PlannerInfo *root, MemoizePath *best_path, int flags)
 
 	nkeys = list_length(param_exprs);
 	Assert(nkeys > 0);
-	operators = palloc(nkeys * sizeof(Oid));
-	collations = palloc(nkeys * sizeof(Oid));
+	operators = palloc_array(Oid, nkeys);
+	collations = palloc_array(Oid, nkeys);
 
 	i = 0;
 	forboth(lc, param_exprs, lc2, best_path->hash_operators)
@@ -2278,7 +2278,7 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
 			maxref = gc->tleSortGroupRef;
 	}
 
-	grouping_map = (AttrNumber *) palloc0((maxref + 1) * sizeof(AttrNumber));
+	grouping_map = palloc0_array(AttrNumber, maxref + 1);
 
 	/* Now look up the column numbers in the child's tlist */
 	foreach(lc, root->processed_groupClause)
@@ -2717,9 +2717,9 @@ create_limit_plan(PlannerInfo *root, LimitPath *best_path, int flags)
 		ListCell   *l;
 
 		numUniqkeys = list_length(parse->sortClause);
-		uniqColIdx = (AttrNumber *) palloc(numUniqkeys * sizeof(AttrNumber));
-		uniqOperators = (Oid *) palloc(numUniqkeys * sizeof(Oid));
-		uniqCollations = (Oid *) palloc(numUniqkeys * sizeof(Oid));
+		uniqColIdx = palloc_array(AttrNumber, numUniqkeys);
+		uniqOperators = palloc_array(Oid, numUniqkeys);
+		uniqCollations = palloc_array(Oid, numUniqkeys);
 
 		numUniqkeys = 0;
 		foreach(l, parse->sortClause)
@@ -4546,10 +4546,10 @@ create_mergejoin_plan(PlannerInfo *root,
 	 */
 	nClauses = list_length(mergeclauses);
 	Assert(nClauses == list_length(best_path->path_mergeclauses));
-	mergefamilies = (Oid *) palloc(nClauses * sizeof(Oid));
-	mergecollations = (Oid *) palloc(nClauses * sizeof(Oid));
-	mergereversals = (bool *) palloc(nClauses * sizeof(bool));
-	mergenullsfirst = (bool *) palloc(nClauses * sizeof(bool));
+	mergefamilies = palloc_array(Oid, nClauses);
+	mergecollations = palloc_array(Oid, nClauses);
+	mergereversals = palloc_array(bool, nClauses);
+	mergenullsfirst = palloc_array(bool, nClauses);
 
 	opathkey = NULL;
 	opeclass = NULL;
@@ -5313,7 +5313,7 @@ order_qual_clauses(PlannerInfo *root, List *clauses)
 	 * Collect the items and costs into an array.  This is to avoid repeated
 	 * cost_qual_eval work if the inputs aren't RestrictInfos.
 	 */
-	items = (QualItem *) palloc(nitems * sizeof(QualItem));
+	items = palloc_array(QualItem, nitems);
 	i = 0;
 	foreach(lc, clauses)
 	{
@@ -6199,10 +6199,10 @@ prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys,
 	 * We will need at most list_length(pathkeys) sort columns; possibly less
 	 */
 	numsortkeys = list_length(pathkeys);
-	sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
-	sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
-	collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
-	nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
+	sortColIdx = palloc_array(AttrNumber, numsortkeys);
+	sortOperators = palloc_array(Oid, numsortkeys);
+	collations = palloc_array(Oid, numsortkeys);
+	nullsFirst = palloc_array(bool, numsortkeys);
 
 	numsortkeys = 0;
 
@@ -6440,10 +6440,10 @@ make_sort_from_sortclauses(List *sortcls, Plan *lefttree)
 
 	/* Convert list-ish representation to arrays wanted by executor */
 	numsortkeys = list_length(sortcls);
-	sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
-	sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
-	collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
-	nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
+	sortColIdx = palloc_array(AttrNumber, numsortkeys);
+	sortOperators = palloc_array(Oid, numsortkeys);
+	collations = palloc_array(Oid, numsortkeys);
+	nullsFirst = palloc_array(bool, numsortkeys);
 
 	numsortkeys = 0;
 	foreach(l, sortcls)
@@ -6491,10 +6491,10 @@ make_sort_from_groupcols(List *groupcls,
 
 	/* Convert list-ish representation to arrays wanted by executor */
 	numsortkeys = list_length(groupcls);
-	sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
-	sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
-	collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
-	nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
+	sortColIdx = palloc_array(AttrNumber, numsortkeys);
+	sortOperators = palloc_array(Oid, numsortkeys);
+	collations = palloc_array(Oid, numsortkeys);
+	nullsFirst = palloc_array(bool, numsortkeys);
 
 	numsortkeys = 0;
 	foreach(l, groupcls)
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index a0ff9159ae0..a605387dcaa 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -2492,7 +2492,7 @@ preprocess_grouping_sets(PlannerInfo *root)
 	}
 
 	/* Allocate workspace array for remapping */
-	gd->tleref_to_colnum_map = (int *) palloc((maxref + 1) * sizeof(int));
+	gd->tleref_to_colnum_map = palloc_array(int, maxref + 1);
 
 	/*
 	 * If we have any unsortable sets, we must extract them before trying to
@@ -3246,10 +3246,10 @@ extract_rollup_sets(List *groupingSets)
 	 * to leave 0 free for the NIL node in the graph algorithm.
 	 *----------
 	 */
-	orig_sets = palloc0((num_sets_raw + 1) * sizeof(List *));
-	set_masks = palloc0((num_sets_raw + 1) * sizeof(Bitmapset *));
-	adjacency = palloc0((num_sets_raw + 1) * sizeof(short *));
-	adjacency_buf = palloc((num_sets_raw + 1) * sizeof(short));
+	orig_sets = palloc0_array(List *, num_sets_raw + 1);
+	set_masks = palloc0_array(Bitmapset *, num_sets_raw + 1);
+	adjacency = palloc0_array(short *, num_sets_raw + 1);
+	adjacency_buf = palloc_array(short, num_sets_raw + 1);
 
 	j_size = 0;
 	j = 0;
@@ -3311,7 +3311,7 @@ extract_rollup_sets(List *groupingSets)
 			if (n_adj > 0)
 			{
 				adjacency_buf[0] = n_adj;
-				adjacency[i] = palloc((n_adj + 1) * sizeof(short));
+				adjacency[i] = palloc_array(short, n_adj + 1);
 				memcpy(adjacency[i], adjacency_buf, (n_adj + 1) * sizeof(short));
 			}
 			else
@@ -3334,7 +3334,7 @@ extract_rollup_sets(List *groupingSets)
 	 * pair_vu[v] = u (both will be true, but we check both so that we can do
 	 * it in one pass)
 	 */
-	chains = palloc0((num_sets + 1) * sizeof(int));
+	chains = palloc0_array(int, num_sets + 1);
 
 	for (i = 1; i <= num_sets; ++i)
 	{
@@ -3350,7 +3350,7 @@ extract_rollup_sets(List *groupingSets)
 	}
 
 	/* build result lists. */
-	results = palloc0((num_chains + 1) * sizeof(List *));
+	results = palloc0_array(List *, num_chains + 1);
 
 	for (i = 1; i <= num_sets; ++i)
 	{
@@ -4643,7 +4643,7 @@ consider_groupingsets_paths(PlannerInfo *root,
 			double		scale;
 			int			num_rollups = list_length(gd->rollups);
 			int			k_capacity;
-			int		   *k_weights = palloc(num_rollups * sizeof(int));
+			int		   *k_weights = palloc_array(int, num_rollups);
 			Bitmapset  *hash_items = NULL;
 			int			i;
 
@@ -6697,8 +6697,8 @@ make_sort_input_target(PlannerInfo *root,
 
 	/* Inspect tlist and collect per-column information */
 	ncols = list_length(final_target->exprs);
-	col_is_srf = (bool *) palloc0(ncols * sizeof(bool));
-	postpone_col = (bool *) palloc0(ncols * sizeof(bool));
+	col_is_srf = palloc0_array(bool, ncols);
+	postpone_col = palloc0_array(bool, ncols);
 	have_srf = have_volatile = have_expensive = have_srf_sortcols = false;
 
 	i = 0;
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index e1182255055..8a641402a96 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -347,10 +347,8 @@ set_plan_references(PlannerInfo *root, Plan *plan)
 	/* If needed, create workspace for processing AlternativeSubPlans */
 	if (root->hasAlternativeSubPlans)
 	{
-		root->isAltSubplan = (bool *)
-			palloc0(list_length(glob->subplans) * sizeof(bool));
-		root->isUsedSubplan = (bool *)
-			palloc0(list_length(glob->subplans) * sizeof(bool));
+		root->isAltSubplan = palloc0_array(bool, list_length(glob->subplans));
+		root->isUsedSubplan = palloc0_array(bool, list_length(glob->subplans));
 	}
 
 	/* Now fix the Plan tree */
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 72d39ba30fd..0b3d2571048 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -558,8 +558,7 @@ expand_virtual_generated_columns(PlannerInfo *root, Query *parse,
 		/* this flag will be set below, if needed */
 		rvcontext.wrap_option = REPLACE_WRAP_NONE;
 		/* initialize cache array with indexes 0 .. length(tlist) */
-		rvcontext.rv_cache = palloc0((list_length(tlist) + 1) *
-									 sizeof(Node *));
+		rvcontext.rv_cache = palloc0_array(Node *, list_length(tlist) + 1);
 
 		/*
 		 * If the query uses grouping sets, we need a PlaceHolderVar for each
@@ -1598,8 +1597,7 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
 	/* this flag will be set below, if needed */
 	rvcontext.wrap_option = REPLACE_WRAP_NONE;
 	/* initialize cache array with indexes 0 .. length(tlist) */
-	rvcontext.rv_cache = palloc0((list_length(subquery->targetList) + 1) *
-								 sizeof(Node *));
+	rvcontext.rv_cache = palloc0_array(Node *, list_length(subquery->targetList) + 1);
 
 	/*
 	 * If the parent query uses grouping sets, we need a PlaceHolderVar for
@@ -1925,8 +1923,7 @@ make_setop_translation_list(Query *query, int newvarno,
 	/* Initialize reverse-translation array with all entries zero */
 	/* (entries for resjunk columns will stay that way) */
 	appinfo->num_child_cols = list_length(query->targetList);
-	appinfo->parent_colnos = pcolnos =
-		(AttrNumber *) palloc0(appinfo->num_child_cols * sizeof(AttrNumber));
+	appinfo->parent_colnos = pcolnos = palloc0_array(AttrNumber, appinfo->num_child_cols);
 
 	foreach(l, query->targetList)
 	{
@@ -2143,8 +2140,7 @@ pull_up_simple_values(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
 	rvcontext.varno = varno;
 	rvcontext.wrap_option = REPLACE_WRAP_NONE;
 	/* initialize cache array with indexes 0 .. length(tlist) */
-	rvcontext.rv_cache = palloc0((list_length(tlist) + 1) *
-								 sizeof(Node *));
+	rvcontext.rv_cache = palloc0_array(Node *, list_length(tlist) + 1);
 
 	/*
 	 * Replace all of the top query's references to the RTE's outputs with
@@ -2311,8 +2307,7 @@ pull_up_constant_function(PlannerInfo *root, Node *jtnode,
 	/* this flag will be set below, if needed */
 	rvcontext.wrap_option = REPLACE_WRAP_NONE;
 	/* initialize cache array with indexes 0 .. length(tlist) */
-	rvcontext.rv_cache = palloc0((list_length(rvcontext.targetlist) + 1) *
-								 sizeof(Node *));
+	rvcontext.rv_cache = palloc0_array(Node *, list_length(rvcontext.targetlist) + 1);
 
 	/*
 	 * If the parent query uses grouping sets, we need a PlaceHolderVar for
diff --git a/src/backend/optimizer/util/appendinfo.c b/src/backend/optimizer/util/appendinfo.c
index 778e4662f6e..ebb74c53d3b 100644
--- a/src/backend/optimizer/util/appendinfo.c
+++ b/src/backend/optimizer/util/appendinfo.c
@@ -94,8 +94,7 @@ make_inh_translation_list(Relation oldrelation, Relation newrelation,
 
 	/* Initialize reverse-translation array with all entries zero */
 	appinfo->num_child_cols = newnatts;
-	appinfo->parent_colnos = pcolnos =
-		(AttrNumber *) palloc0(newnatts * sizeof(AttrNumber));
+	appinfo->parent_colnos = pcolnos = palloc0_array(AttrNumber, newnatts);
 
 	for (old_attno = 0; old_attno < oldnatts; old_attno++)
 	{
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 337fc27262e..c92b0f3dbb4 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -263,7 +263,7 @@ find_window_functions(Node *clause, Index maxWinRef)
 
 	lists->numWindowFuncs = 0;
 	lists->maxWinRef = maxWinRef;
-	lists->windowFuncs = (List **) palloc0((maxWinRef + 1) * sizeof(List *));
+	lists->windowFuncs = palloc0_array(List *, (maxWinRef + 1));
 	(void) find_window_functions_walker(clause, lists);
 	return lists;
 }
@@ -5576,7 +5576,7 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid,
 	 * substitution of the inputs.  So start building expression with inputs
 	 * substituted.
 	 */
-	usecounts = (int *) palloc0(funcform->pronargs * sizeof(int));
+	usecounts = palloc0_array(int, funcform->pronargs);
 	newexpr = substitute_actual_parameters(newexpr, funcform->pronargs,
 										   args, usecounts);
 
diff --git a/src/backend/optimizer/util/inherit.c b/src/backend/optimizer/util/inherit.c
index 6a7b9edff3f..6e1d2b14bc4 100644
--- a/src/backend/optimizer/util/inherit.c
+++ b/src/backend/optimizer/util/inherit.c
@@ -360,8 +360,7 @@ expand_partitioned_rtentry(PlannerInfo *root, RelOptInfo *relinfo,
 	 * contain NULL.
 	 */
 	Assert(relinfo->part_rels == NULL);
-	relinfo->part_rels = (RelOptInfo **)
-		palloc0(relinfo->nparts * sizeof(RelOptInfo *));
+	relinfo->part_rels = palloc0_array(RelOptInfo *, relinfo->nparts);
 
 	/*
 	 * Create a child RTE for each live partition.  Note that unlike
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 7c4be174869..4c9c5e9fc33 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -162,10 +162,8 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 	rel->reltablespace = RelationGetForm(relation)->reltablespace;
 
 	Assert(rel->max_attr >= rel->min_attr);
-	rel->attr_needed = (Relids *)
-		palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));
-	rel->attr_widths = (int32 *)
-		palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));
+	rel->attr_needed = palloc0_array(Relids, rel->max_attr - rel->min_attr + 1);
+	rel->attr_widths = palloc0_array(int32, rel->max_attr - rel->min_attr + 1);
 
 	/*
 	 * Record which columns are defined as NOT NULL.  We leave this
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c
index 752ea9222f6..3bef96acb54 100644
--- a/src/backend/optimizer/util/tlist.c
+++ b/src/backend/optimizer/util/tlist.c
@@ -603,7 +603,7 @@ make_pathtarget_from_tlist(List *tlist)
 	int			i;
 	ListCell   *lc;
 
-	target->sortgrouprefs = (Index *) palloc(list_length(tlist) * sizeof(Index));
+	target->sortgrouprefs = palloc_array(Index, list_length(tlist));
 
 	i = 0;
 	foreach(lc, tlist)
@@ -720,7 +720,7 @@ add_column_to_pathtarget(PathTarget *target, Expr *expr, Index sortgroupref)
 		/* Adding sortgroupref labeling to a previously unlabeled target */
 		int			nexprs = list_length(target->exprs);
 
-		target->sortgrouprefs = (Index *) palloc0(nexprs * sizeof(Index));
+		target->sortgrouprefs = palloc0_array(Index, nexprs);
 		target->sortgrouprefs[nexprs - 1] = sortgroupref;
 	}
 
@@ -1307,8 +1307,8 @@ add_sp_item_to_pathtarget(PathTarget *target, split_pathtarget_item *item)
 			{
 				if (target->sortgrouprefs == NULL)
 				{
-					target->sortgrouprefs = (Index *)
-						palloc0(list_length(target->exprs) * sizeof(Index));
+					target->sortgrouprefs = palloc0_array(Index,
+														  list_length(target->exprs));
 				}
 				target->sortgrouprefs[lci] = item->sortgroupref;
 			}
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 581457c69c9..263d1b6e1cc 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -1955,7 +1955,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
 			/* Remember post-transformation length of first sublist */
 			sublist_length = list_length(sublist);
 			/* and allocate array for per-column lists */
-			colexprs = (List **) palloc0(sublist_length * sizeof(List *));
+			colexprs = palloc0_array(List *, sublist_length);
 		}
 		else if (sublist_length != list_length(sublist))
 		{
@@ -2227,8 +2227,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
 	qry->targetList = NIL;
 	targetvars = NIL;
 	targetnames = NIL;
-	sortnscolumns = (ParseNamespaceColumn *)
-		palloc0(list_length(sostmt->colTypes) * sizeof(ParseNamespaceColumn));
+	sortnscolumns = palloc0_array(ParseNamespaceColumn, list_length(sostmt->colTypes));
 	sortcolindex = 0;
 
 	forfour(lct, sostmt->colTypes,
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 68b525ffdcc..67de2733d8a 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -1466,9 +1466,8 @@ transformFromClauseItem(ParseState *pstate, Node *n,
 		res_colvars = NIL;
 
 		/* this may be larger than needed, but it's not worth being exact */
-		res_nscolumns = (ParseNamespaceColumn *)
-			palloc0((list_length(l_colnames) + list_length(r_colnames)) *
-					sizeof(ParseNamespaceColumn));
+		res_nscolumns = palloc0_array(ParseNamespaceColumn,
+									  list_length(l_colnames) + list_length(r_colnames));
 		res_colindex = 0;
 
 		if (j->usingClause)
diff --git a/src/backend/parser/parse_cte.c b/src/backend/parser/parse_cte.c
index ccde199319a..73e86b7422f 100644
--- a/src/backend/parser/parse_cte.c
+++ b/src/backend/parser/parse_cte.c
@@ -166,7 +166,7 @@ transformWithClause(ParseState *pstate, WithClause *withClause)
 
 		cstate.pstate = pstate;
 		cstate.numitems = list_length(withClause->ctes);
-		cstate.items = (CteItem *) palloc0(cstate.numitems * sizeof(CteItem));
+		cstate.items = palloc0_array(CteItem, cstate.numitems);
 		i = 0;
 		foreach(lc, withClause->ctes)
 		{
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 66f501aaf49..4cbba861851 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -1347,8 +1347,7 @@ buildNSItemFromTupleDesc(RangeTblEntry *rte, Index rtindex,
 	Assert(maxattrs == list_length(rte->eref->colnames));
 
 	/* extract per-column data from the tupdesc */
-	nscolumns = (ParseNamespaceColumn *)
-		palloc0(maxattrs * sizeof(ParseNamespaceColumn));
+	nscolumns = palloc0_array(ParseNamespaceColumn, maxattrs);
 
 	for (varattno = 0; varattno < maxattrs; varattno++)
 	{
@@ -1413,8 +1412,7 @@ buildNSItemFromLists(RangeTblEntry *rte, Index rtindex,
 	Assert(maxattrs == list_length(colcollations));
 
 	/* extract per-column data from the lists */
-	nscolumns = (ParseNamespaceColumn *)
-		palloc0(maxattrs * sizeof(ParseNamespaceColumn));
+	nscolumns = palloc0_array(ParseNamespaceColumn, maxattrs);
 
 	varattno = 0;
 	forthree(lct, coltypes,
diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c
index b5c28523971..5ec345f08f6 100644
--- a/src/backend/parser/parser.c
+++ b/src/backend/parser/parser.c
@@ -384,7 +384,7 @@ str_udeescape(const char *str, char escape,
 	 * padding for Unicode conversion.
 	 */
 	new_len = strlen(str) + MAX_UNICODE_EQUIVALENT_STRING + 1;
-	new = palloc(new_len);
+	new = palloc_array(char, new_len);
 
 	in = str;
 	out = new;
diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l
index ee6c34cc14b..b7d0d7c2ff9 100644
--- a/src/backend/parser/scan.l
+++ b/src/backend/parser/scan.l
@@ -1251,7 +1251,7 @@ scanner_init(const char *str,
 	/*
 	 * Make a scan buffer with special termination needed by flex.
 	 */
-	yyext->scanbuf = (char *) palloc(slen + 2);
+	yyext->scanbuf = palloc_array(char, slen + 2);
 	yyext->scanbuflen = slen;
 	memcpy(yyext->scanbuf, str, slen);
 	yyext->scanbuf[slen] = yyext->scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR;
@@ -1259,7 +1259,7 @@ scanner_init(const char *str,
 
 	/* initialize literal buffer to a reasonable but expansible size */
 	yyext->literalalloc = 1024;
-	yyext->literalbuf = (char *) palloc(yyext->literalalloc);
+	yyext->literalbuf = palloc_array(char, yyext->literalalloc);
 	yyext->literallen = 0;
 
 	return scanner;
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index a7822a4192b..865a92c8561 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -387,7 +387,7 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	boundinfo->kind = NULL;
 	boundinfo->interleaved_parts = NULL;
 	boundinfo->nindexes = greatest_modulus;
-	boundinfo->indexes = (int *) palloc(greatest_modulus * sizeof(int));
+	boundinfo->indexes = palloc_array(int, greatest_modulus);
 	for (i = 0; i < greatest_modulus; i++)
 		boundinfo->indexes[i] = -1;
 
@@ -396,7 +396,7 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	 * arrays, here we just allocate a single array and below we'll just
 	 * assign a portion of this array per partition.
 	 */
-	boundDatums = (Datum *) palloc(nparts * 2 * sizeof(Datum));
+	boundDatums = palloc_array(Datum, nparts * 2);
 
 	/*
 	 * For hash partitioning, there are as many datums (modulus and remainder
@@ -478,8 +478,7 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	boundinfo->default_index = -1;
 
 	ndatums = get_non_null_list_datum_count(boundspecs, nparts);
-	all_values = (PartitionListValue *)
-		palloc(ndatums * sizeof(PartitionListValue));
+	all_values = palloc_array(PartitionListValue, ndatums);
 
 	/* Create a unified list of non-null values across all partitions. */
 	for (j = 0, i = 0; i < nparts; i++)
@@ -535,14 +534,14 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	boundinfo->kind = NULL;
 	boundinfo->interleaved_parts = NULL;
 	boundinfo->nindexes = ndatums;
-	boundinfo->indexes = (int *) palloc(ndatums * sizeof(int));
+	boundinfo->indexes = palloc_array(int, ndatums);
 
 	/*
 	 * In the loop below, to save from allocating a series of small datum
 	 * arrays, here we just allocate a single array and below we'll just
 	 * assign a portion of this array per datum.
 	 */
-	boundDatums = (Datum *) palloc(ndatums * sizeof(Datum));
+	boundDatums = palloc_array(Datum, ndatums);
 
 	/*
 	 * Copy values.  Canonical indexes are values ranging from 0 to (nparts -
@@ -735,8 +734,7 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
 			  key);
 
 	/* Save distinct bounds from all_bounds into rbounds. */
-	rbounds = (PartitionRangeBound **)
-		palloc(ndatums * sizeof(PartitionRangeBound *));
+	rbounds = palloc_array(PartitionRangeBound *, ndatums);
 	k = 0;
 	prev = NULL;
 	for (i = 0; i < ndatums; i++)
@@ -817,7 +815,7 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	 * arrays in each loop.
 	 */
 	partnatts = key->partnatts;
-	boundDatums = (Datum *) palloc(ndatums * partnatts * sizeof(Datum));
+	boundDatums = palloc_array(Datum, ndatums * partnatts);
 	boundKinds = palloc_array(PartitionRangeDatumKind, ndatums * partnatts);
 
 	for (i = 0; i < ndatums; i++)
@@ -1020,16 +1018,14 @@ partition_bounds_copy(PartitionBoundInfo src,
 		/* only RANGE partition should have a non-NULL kind */
 		Assert(key->strategy == PARTITION_STRATEGY_RANGE);
 
-		dest->kind = (PartitionRangeDatumKind **) palloc(ndatums *
-														 sizeof(PartitionRangeDatumKind *));
+		dest->kind = palloc_array(PartitionRangeDatumKind *, ndatums);
 
 		/*
 		 * In the loop below, to save from allocating a series of small arrays
 		 * for storing the PartitionRangeDatumKind, we allocate a single chunk
 		 * here and use a smaller portion of it for each datum.
 		 */
-		boundKinds = (PartitionRangeDatumKind *) palloc(ndatums * partnatts *
-														sizeof(PartitionRangeDatumKind));
+		boundKinds = palloc_array(PartitionRangeDatumKind, ndatums * partnatts);
 
 		for (i = 0; i < ndatums; i++)
 		{
@@ -1052,7 +1048,7 @@ partition_bounds_copy(PartitionBoundInfo src,
 	{
 		bool		hash_part = (key->strategy == PARTITION_STRATEGY_HASH);
 		int			natts = hash_part ? 2 : partnatts;
-		Datum	   *boundDatums = palloc(ndatums * natts * sizeof(Datum));
+		Datum	   *boundDatums = palloc_array(Datum, ndatums * natts);
 
 		for (i = 0; i < ndatums; i++)
 		{
diff --git a/src/backend/partitioning/partdesc.c b/src/backend/partitioning/partdesc.c
index 5a8987bb3c5..f29e5a323a1 100644
--- a/src/backend/partitioning/partdesc.c
+++ b/src/backend/partitioning/partdesc.c
@@ -171,9 +171,9 @@ RelationBuildPartitionDesc(Relation rel, bool omit_detached)
 	/* Allocate working arrays for OIDs, leaf flags, and boundspecs. */
 	if (nparts > 0)
 	{
-		oids = (Oid *) palloc(nparts * sizeof(Oid));
-		is_leaf = (bool *) palloc(nparts * sizeof(bool));
-		boundspecs = palloc(nparts * sizeof(PartitionBoundSpec *));
+		oids = palloc_array(Oid, nparts);
+		is_leaf = palloc_array(bool, nparts);
+		boundspecs = palloc_array(PartitionBoundSpec *, nparts);
 	}
 
 	/* Collect bound spec nodes for each partition. */
@@ -335,8 +335,8 @@ RelationBuildPartitionDesc(Relation rel, bool omit_detached)
 		partdesc->last_found_datum_index = -1;
 		partdesc->last_found_count = 0;
 
-		partdesc->oids = (Oid *) palloc(nparts * sizeof(Oid));
-		partdesc->is_leaf = (bool *) palloc(nparts * sizeof(bool));
+		partdesc->oids = palloc_array(Oid, nparts);
+		partdesc->is_leaf = palloc_array(bool, nparts);
 
 		/*
 		 * Assign OIDs from the original array into mapped indexes of the
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index afe57ac297d..06566c8ce8a 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -654,12 +654,12 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
 		 * Also construct a Bitmapset of all partitions that are present (that
 		 * is, not pruned already).
 		 */
-		subplan_map = (int *) palloc(nparts * sizeof(int));
+		subplan_map = palloc_array(int, nparts);
 		memset(subplan_map, -1, nparts * sizeof(int));
-		subpart_map = (int *) palloc(nparts * sizeof(int));
+		subpart_map = palloc_array(int, nparts);
 		memset(subpart_map, -1, nparts * sizeof(int));
-		relid_map = (Oid *) palloc0(nparts * sizeof(Oid));
-		leafpart_rti_map = (int *) palloc0(nparts * sizeof(int));
+		relid_map = palloc0_array(Oid, nparts);
+		leafpart_rti_map = palloc0_array(int, nparts);
 		present_parts = NULL;
 
 		i = -1;
@@ -867,8 +867,7 @@ get_matching_partitions(PartitionPruneContext *context, List *pruning_steps)
 	 * result of applying all pruning steps is the value contained in the slot
 	 * of the last pruning step.
 	 */
-	results = (PruneStepResult **)
-		palloc0(num_steps * sizeof(PruneStepResult *));
+	results = palloc0_array(PruneStepResult *, num_steps);
 	foreach(lc, pruning_steps)
 	{
 		PartitionPruneStep *step = lfirst(lc);
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index ee202a4b47e..b877d8fd2de 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -1057,7 +1057,7 @@ rebuild_database_list(Oid newdb)
 		int			i;
 
 		/* put all the hash elements into an array */
-		dbary = palloc(nelems * sizeof(avl_dbase));
+		dbary = palloc_array(avl_dbase, nelems);
 		/* keep Valgrind quiet */
 #ifdef USE_VALGRIND
 		avl_dbase_array = dbary;
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index f6351f1eb10..580c7944119 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -1459,7 +1459,7 @@ AbsorbSyncRequests(void)
 		if (n > 0)
 		{
 			if (!requests)
-				requests = (CheckpointerRequest *) palloc(n * sizeof(CheckpointerRequest));
+				requests = palloc_array(CheckpointerRequest, n);
 
 			for (i = 0; i < n; i++)
 			{
diff --git a/src/backend/postmaster/pmchild.c b/src/backend/postmaster/pmchild.c
index 5c4c66fe76f..312cb2d8aba 100644
--- a/src/backend/postmaster/pmchild.c
+++ b/src/backend/postmaster/pmchild.c
@@ -137,7 +137,7 @@ InitPostmasterChildSlots(void)
 		num_pmchild_slots += pmchild_pools[i].size;
 
 	/* Allocate enough slots, and make sure Valgrind doesn't complain */
-	slots = palloc(num_pmchild_slots * sizeof(PMChild));
+	slots = palloc_array(PMChild, num_pmchild_slots);
 #ifdef USE_VALGRIND
 	pmchild_array = slots;
 #endif
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 90c7c4528e8..1711743f1ac 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -1123,7 +1123,7 @@ PostmasterMain(int argc, char *argv[])
 	 * First set up an on_proc_exit function that's charged with closing the
 	 * sockets again at postmaster shutdown.
 	 */
-	ListenSockets = palloc(MAXLISTEN * sizeof(pgsocket));
+	ListenSockets = palloc_array(pgsocket, MAXLISTEN);
 	on_proc_exit(CloseServerPorts, 0);
 
 	if (ListenAddresses)
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index f60bcf09605..891ed8e22a1 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1602,7 +1602,7 @@ SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn)
 	needed_length = sizeof(SnapBuildOnDisk) +
 		sizeof(TransactionId) * (builder->committed.xcnt + catchange_xcnt);
 
-	ondisk_c = palloc0(needed_length);
+	ondisk_c = palloc0_array(char, needed_length);
 	ondisk = (SnapBuildOnDisk *) ondisk_c;
 	ondisk->magic = SNAPBUILD_MAGIC;
 	ondisk->version = SNAPBUILD_VERSION;
diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index e5101997cd3..68a6f46b918 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -1293,7 +1293,7 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
 	}
 
 	/* Calculate the name of the tablesync slot. */
-	slotname = (char *) palloc(NAMEDATALEN);
+	slotname = palloc_array(char, NAMEDATALEN);
 	ReplicationSlotNameForTablesync(MySubscription->oid,
 									MyLogicalRepWorker->relid,
 									slotname,
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 92ea1d0df24..8a31bcc16a0 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -2314,7 +2314,7 @@ apply_spooled_messages(FileSet *stream_fileset, TransactionId xid,
 
 	CurrentResourceOwner = oldowner;
 
-	buffer = palloc(BLCKSZ);
+	buffer = palloc_array(char, BLCKSZ);
 
 	MemoryContextSwitchTo(oldcxt);
 
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index 0afdb1432ca..484ffbe2cee 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -1672,7 +1672,7 @@ pgoutput_truncate(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
 
 	old = MemoryContextSwitchTo(data->context);
 
-	relids = palloc0(nrelations * sizeof(Oid));
+	relids = palloc0_array(Oid, nrelations);
 	nrelids = 0;
 
 	for (i = 0; i < nrelations; i++)
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 38f54b57eec..29c95a21577 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -848,7 +848,7 @@ rewriteTargetListIU(List *targetList,
 	 * scan, then appended to the reconstructed tlist.
 	 */
 	numattrs = RelationGetNumberOfAttributes(target_relation);
-	new_tles = (TargetEntry **) palloc0(numattrs * sizeof(TargetEntry *));
+	new_tles = palloc0_array(TargetEntry *, numattrs);
 	next_junk_attrno = numattrs + 1;
 
 	foreach(temp, targetList)
@@ -1492,7 +1492,7 @@ rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti,
 	 * columns), and we complain if such a thing does occur.
 	 */
 	numattrs = list_length(linitial(rte->values_lists));
-	attrnos = (int *) palloc0(numattrs * sizeof(int));
+	attrnos = palloc0_array(int, numattrs);
 
 	foreach(lc, parsetree->targetList)
 	{
diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c
index 332e7423bd8..4c3c72e083e 100644
--- a/src/backend/statistics/extended_stats.c
+++ b/src/backend/statistics/extended_stats.c
@@ -737,7 +737,7 @@ lookup_var_attr_stats(Bitmapset *attrs, List *exprs,
 
 	natts = bms_num_members(attrs) + list_length(exprs);
 
-	stats = (VacAttrStats **) palloc(natts * sizeof(VacAttrStats *));
+	stats = palloc_array(VacAttrStats *, natts);
 
 	/* lookup VacAttrStats info for the requested columns (same attnum) */
 	while ((x = bms_next_member(attrs, x)) >= 0)
@@ -1049,7 +1049,7 @@ build_sorted_items(StatsBuildData *data, int *nitems,
 		nvalues * (sizeof(Datum) + sizeof(bool));
 
 	/* Allocate the memory and split it into the pieces. */
-	ptr = palloc0(len);
+	ptr = palloc0_array(char, len);
 
 	/* items to sort */
 	items = (SortItem *) ptr;
@@ -2175,8 +2175,8 @@ compute_expr_stats(Relation onerel, AnlExprData *exprdata, int nexprs,
 		econtext->ecxt_scantuple = slot;
 
 		/* Compute and save expression values */
-		exprvals = (Datum *) palloc(numrows * sizeof(Datum));
-		exprnulls = (bool *) palloc(numrows * sizeof(bool));
+		exprvals = palloc_array(Datum, numrows);
+		exprnulls = palloc_array(bool, numrows);
 
 		tcnt = 0;
 		for (i = 0; i < numrows; i++)
@@ -2293,7 +2293,7 @@ build_expr_data(List *exprs, int stattarget)
 	AnlExprData *exprdata;
 	ListCell   *lc;
 
-	exprdata = (AnlExprData *) palloc0(nexprs * sizeof(AnlExprData));
+	exprdata = palloc0_array(AnlExprData, nexprs);
 
 	idx = 0;
 	foreach(lc, exprs)
@@ -2386,7 +2386,7 @@ serialize_expr_stats(AnlExprData *exprdata, int nexprs)
 			if (nnum > 0)
 			{
 				int			n;
-				Datum	   *numdatums = (Datum *) palloc(nnum * sizeof(Datum));
+				Datum	   *numdatums = palloc_array(Datum, nnum);
 				ArrayType  *arry;
 
 				for (n = 0; n < nnum; n++)
diff --git a/src/backend/statistics/extended_stats_funcs.c b/src/backend/statistics/extended_stats_funcs.c
index a3e56933b91..7d316e9e003 100644
--- a/src/backend/statistics/extended_stats_funcs.c
+++ b/src/backend/statistics/extended_stats_funcs.c
@@ -984,7 +984,7 @@ jbv_string_get_cstr(JsonbValue *jval)
 
 	Assert(jval->type == jbvString);
 
-	s = palloc0(jval->val.string.len + 1);
+	s = palloc0_array(char, jval->val.string.len + 1);
 	memcpy(s, jval->val.string.val, jval->val.string.len);
 
 	return s;
diff --git a/src/backend/statistics/mcv.c b/src/backend/statistics/mcv.c
index 3e90f600ebe..10a91c97aeb 100644
--- a/src/backend/statistics/mcv.c
+++ b/src/backend/statistics/mcv.c
@@ -426,7 +426,7 @@ build_distinct_groups(int numrows, SortItem *items, MultiSortSupport mss,
 				j;
 	int			ngroups = count_distinct_groups(numrows, items, mss);
 
-	SortItem   *groups = (SortItem *) palloc(ngroups * sizeof(SortItem));
+	SortItem   *groups = palloc_array(SortItem, ngroups);
 
 	j = 0;
 	groups[0] = items[0];
@@ -1094,7 +1094,7 @@ statext_mcv_deserialize(bytea *data)
 	ptr += (sizeof(Oid) * ndims);
 
 	/* Now it's safe to access the dimension info. */
-	info = palloc(ndims * sizeof(DimensionInfo));
+	info = palloc_array(DimensionInfo, ndims);
 
 	memcpy(info, ptr, ndims * sizeof(DimensionInfo));
 	ptr += (ndims * sizeof(DimensionInfo));
diff --git a/src/backend/statistics/mvdistinct.c b/src/backend/statistics/mvdistinct.c
index a6a904039e5..601f108a2b4 100644
--- a/src/backend/statistics/mvdistinct.c
+++ b/src/backend/statistics/mvdistinct.c
@@ -307,8 +307,7 @@ statext_ndistinct_deserialize(bytea *data)
 		tmp += sizeof(int);
 		Assert((item->nattributes >= 2) && (item->nattributes <= STATS_MAX_DIMENSIONS));
 
-		item->attributes
-			= (AttrNumber *) palloc(item->nattributes * sizeof(AttrNumber));
+		item->attributes = palloc_array(AttrNumber, item->nattributes);
 
 		memcpy(item->attributes, tmp, sizeof(AttrNumber) * item->nattributes);
 		tmp += sizeof(AttrNumber) * item->nattributes;
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 169829eb020..17f142e4c5b 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -4948,7 +4948,7 @@ DropRelationsAllBuffers(SMgrRelation *smgr_reln, int nlocators)
 	 * forks.
 	 */
 	block = (BlockNumber (*)[MAX_FORKNUM + 1])
-		palloc(sizeof(BlockNumber) * n * (MAX_FORKNUM + 1));
+		palloc_array(BlockNumber, n * (MAX_FORKNUM + 1));
 
 	/*
 	 * We can avoid scanning the entire buffer pool if we know the exact size
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index e8c07805f59..d7b3bc51f59 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -873,7 +873,7 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 		 * ensure it is reasonably well-aligned; this may save a few cycles
 		 * transferring data to the kernel.
 		 */
-		char	   *zbuffer = (char *) palloc0(ZBUFFER_SIZE);
+		char	   *zbuffer = palloc0_array(char, ZBUFFER_SIZE);
 		Size		remaining = request_size;
 		bool		success = true;
 
diff --git a/src/backend/storage/lmgr/deadlock.c b/src/backend/storage/lmgr/deadlock.c
index b8962d875b6..b6356f72a4e 100644
--- a/src/backend/storage/lmgr/deadlock.c
+++ b/src/backend/storage/lmgr/deadlock.c
@@ -151,16 +151,16 @@ InitDeadLockChecking(void)
 	 * FindLockCycle needs at most MaxBackends entries in visitedProcs[] and
 	 * deadlockDetails[].
 	 */
-	visitedProcs = (PGPROC **) palloc(MaxBackends * sizeof(PGPROC *));
-	deadlockDetails = (DEADLOCK_INFO *) palloc(MaxBackends * sizeof(DEADLOCK_INFO));
+	visitedProcs = palloc_array(PGPROC *, MaxBackends);
+	deadlockDetails = palloc_array(DEADLOCK_INFO, MaxBackends);
 
 	/*
 	 * TopoSort needs to consider at most MaxBackends wait-queue entries, and
 	 * it needn't run concurrently with FindLockCycle.
 	 */
 	topoProcs = visitedProcs;	/* re-use this space */
-	beforeConstraints = (int *) palloc(MaxBackends * sizeof(int));
-	afterConstraints = (int *) palloc(MaxBackends * sizeof(int));
+	beforeConstraints = palloc_array(int, MaxBackends);
+	afterConstraints = palloc_array(int, MaxBackends);
 
 	/*
 	 * We need to consider rearranging at most MaxBackends/2 wait queues
@@ -168,9 +168,8 @@ InitDeadLockChecking(void)
 	 * and the expanded form of the wait queues can't involve more than
 	 * MaxBackends total waiters.
 	 */
-	waitOrders = (WAIT_ORDER *)
-		palloc((MaxBackends / 2) * sizeof(WAIT_ORDER));
-	waitOrderProcs = (PGPROC **) palloc(MaxBackends * sizeof(PGPROC *));
+	waitOrders = palloc_array(WAIT_ORDER, MaxBackends / 2);
+	waitOrderProcs = palloc_array(PGPROC *, MaxBackends);
 
 	/*
 	 * Allow at most MaxBackends distinct constraints in a configuration. (Is
@@ -181,7 +180,7 @@ InitDeadLockChecking(void)
 	 * really big might potentially allow a stack-overflow problem.
 	 */
 	maxCurConstraints = MaxBackends;
-	curConstraints = (EDGE *) palloc(maxCurConstraints * sizeof(EDGE));
+	curConstraints = palloc_array(EDGE, maxCurConstraints);
 
 	/*
 	 * Allow up to 3*MaxBackends constraints to be saved without having to
@@ -195,8 +194,7 @@ InitDeadLockChecking(void)
 		StaticAssertDecl(MAX_BACKENDS_BITS <= (32 - 3),
 						 "MAX_BACKENDS_BITS too big for * 4");
 		maxPossibleConstraints = MaxBackends * 4;
-		possibleConstraints =
-			(EDGE *) palloc(maxPossibleConstraints * sizeof(EDGE));
+		possibleConstraints = palloc_array(EDGE, maxPossibleConstraints);
 	}
 
 	MemoryContextSwitchTo(oldcxt);
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 0608eee9eb2..4178a1f7cf7 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -4172,7 +4172,7 @@ GetRunningTransactionLocks(int *nlocks)
 	 * Allocating enough space for all locks in the lock table is overkill,
 	 * but it's more convenient and faster than having to enlarge the array.
 	 */
-	accessExclusiveLocks = palloc(els * sizeof(xl_standby_lock));
+	accessExclusiveLocks = palloc_array(xl_standby_lock, els);
 
 	/* Now scan the tables to copy the data */
 	hash_seq_init(&seqstat, LockMethodProcLockHash);
diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c
index 52772bc90a8..ddd1d00610c 100644
--- a/src/backend/tcop/fastpath.c
+++ b/src/backend/tcop/fastpath.c
@@ -339,7 +339,7 @@ parse_fcall_arguments(StringInfo msgBuf, struct fp_info *fip,
 	numAFormats = pq_getmsgint(msgBuf, 2);
 	if (numAFormats > 0)
 	{
-		aformats = (int16 *) palloc(numAFormats * sizeof(int16));
+		aformats = palloc_array(int16, numAFormats);
 		for (i = 0; i < numAFormats; i++)
 			aformats[i] = pq_getmsgint(msgBuf, 2);
 	}
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index b6bdfe213fe..a358fb754c5 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -2563,7 +2563,7 @@ truncate_query_log(const char *query)
 
 	/* Truncate at a multibyte character boundary */
 	truncated_len = pg_mbcliplen(query, query_len, log_statement_max_length);
-	truncated_query = (char *) palloc(truncated_len + 4);
+	truncated_query = palloc_array(char, truncated_len + 4);
 	memcpy(truncated_query, query, truncated_len);
 	memcpy(truncated_query + truncated_len, "...", 3);
 	truncated_query[truncated_len + 3] = '\0';
diff --git a/src/backend/tsearch/spell.c b/src/backend/tsearch/spell.c
index 06c90cc0b9f..11f2ed1a182 100644
--- a/src/backend/tsearch/spell.c
+++ b/src/backend/tsearch/spell.c
@@ -2450,7 +2450,7 @@ SplitToVariants(IspellDict *Conf, SPNode *snode, SplitVar *orig, const char *wor
 	/* since this function recurses, it could be driven to stack overflow */
 	check_stack_depth();
 
-	notprobed = (char *) palloc(wordlen);
+	notprobed = palloc_array(char, wordlen);
 	memset(notprobed, 1, wordlen);
 	var = CopyVar(orig, 1);
 
diff --git a/src/backend/tsearch/ts_parse.c b/src/backend/tsearch/ts_parse.c
index 64b62dcd3c0..bee84e10053 100644
--- a/src/backend/tsearch/ts_parse.c
+++ b/src/backend/tsearch/ts_parse.c
@@ -447,7 +447,7 @@ hladdword(HeadlineParsedText *prs, char *buf, int buflen, int type)
 	memset(&(prs->words[prs->curwords]), 0, sizeof(HeadlineWordEntry));
 	prs->words[prs->curwords].type = (uint8) type;
 	prs->words[prs->curwords].len = buflen;
-	prs->words[prs->curwords].word = palloc(buflen);
+	prs->words[prs->curwords].word = palloc_array(char, buflen);
 	memcpy(prs->words[prs->curwords].word, buf, buflen);
 	prs->curwords++;
 }
diff --git a/src/backend/tsearch/wparser_def.c b/src/backend/tsearch/wparser_def.c
index 480915030df..d798d4fb9e7 100644
--- a/src/backend/tsearch/wparser_def.c
+++ b/src/backend/tsearch/wparser_def.c
@@ -2252,7 +2252,7 @@ mark_hl_fragments(HeadlineParsedText *prs, TSQuery query, List *locations,
 				maxitems;
 	CoverPos   *covers;
 
-	covers = palloc(maxcovers * sizeof(CoverPos));
+	covers = palloc_array(CoverPos, maxcovers);
 
 	/* get all covers */
 	while (hlCover(prs, query, locations, &nextpos, &p, &q))
diff --git a/src/backend/utils/activity/pgstat_xact.c b/src/backend/utils/activity/pgstat_xact.c
index 3e1978775e1..820cf97de87 100644
--- a/src/backend/utils/activity/pgstat_xact.c
+++ b/src/backend/utils/activity/pgstat_xact.c
@@ -285,8 +285,7 @@ pgstat_get_transactional_drops(bool isCommit, xl_xact_stats_item **items)
 	Assert(!isCommit || xact_state->nest_level == 1);
 	Assert(!isCommit || xact_state->prev == NULL);
 
-	*items = palloc(dclist_count(&xact_state->pending_drops)
-					* sizeof(xl_xact_stats_item));
+	*items = palloc_array(xl_xact_stats_item, dclist_count(&xact_state->pending_drops));
 
 	dclist_foreach(iter, &xact_state->pending_drops)
 	{
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index e2547d719ed..1e8102cc23e 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -1584,7 +1584,7 @@ aclmembers(const Acl *acl, Oid **roleids)
 	check_acl(acl);
 
 	/* Allocate the worst-case space requirement */
-	list = palloc(ACL_NUM(acl) * 2 * sizeof(Oid));
+	list = palloc_array(Oid, ACL_NUM(acl) * 2);
 	acldat = ACL_DAT(acl);
 
 	/*
diff --git a/src/backend/utils/adt/array_typanalyze.c b/src/backend/utils/adt/array_typanalyze.c
index 7bb000ddbd3..bcc58c5832e 100644
--- a/src/backend/utils/adt/array_typanalyze.c
+++ b/src/backend/utils/adt/array_typanalyze.c
@@ -549,8 +549,8 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
 			 * through all the values.  We also want the frequency of null
 			 * elements.  Store these three values at the end of mcelem_freqs.
 			 */
-			mcelem_values = (Datum *) palloc(num_mcelem * sizeof(Datum));
-			mcelem_freqs = (float4 *) palloc((num_mcelem + 3) * sizeof(float4));
+			mcelem_values = palloc_array(Datum, num_mcelem);
+			mcelem_freqs = palloc_array(float4, num_mcelem + 3);
 
 			/*
 			 * See comments above about use of nonnull_cnt as the divisor for
diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c
index 9d7f67cc188..d81ef83fa7c 100644
--- a/src/backend/utils/adt/array_userfuncs.c
+++ b/src/backend/utils/adt/array_userfuncs.c
@@ -1008,7 +1008,7 @@ array_agg_array_combine(PG_FUNCTION_ARGS)
 									agg_context, false);
 
 		state1->abytes = state2->abytes;
-		state1->data = (char *) palloc(state1->abytes);
+		state1->data = palloc_array(char, state1->abytes);
 
 		if (state2->nullbitmap)
 		{
@@ -1096,7 +1096,7 @@ array_agg_array_combine(PG_FUNCTION_ARGS)
 				 * previous inputs by marking all their items non-null.
 				 */
 				state1->aitems = pg_nextpower2_32(Max(256, newnitems));
-				state1->nullbitmap = (uint8 *) palloc((state1->aitems + 7) / 8);
+				state1->nullbitmap = palloc_array(uint8, (state1->aitems + 7) / 8);
 				array_bitmap_copy(state1->nullbitmap, 0,
 								  NULL, 0,
 								  state1->nitems);
@@ -1229,7 +1229,7 @@ array_agg_array_deserialize(PG_FUNCTION_ARGS)
 	while (result->abytes < nbytes)
 		result->abytes *= 2;
 
-	result->data = (char *) palloc(result->abytes);
+	result->data = palloc_array(char, result->abytes);
 
 	/* data */
 	temp = pq_getmsgbytes(&buf, nbytes);
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 13eed22dd6a..47141a7c4c8 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -1112,8 +1112,8 @@ array_out(PG_FUNCTION_ARGS)
 	 * any overhead such as escaping backslashes), and detect whether each
 	 * item needs double quotes.
 	 */
-	values = (char **) palloc(nitems * sizeof(char *));
-	needquotes = (bool *) palloc(nitems * sizeof(bool));
+	values = palloc_array(char *, nitems);
+	needquotes = palloc_array(bool, nitems);
 	overall_length = 0;
 
 	array_iter_setup(&iter, v, typlen, typbyval, typalign);
@@ -1199,7 +1199,7 @@ array_out(PG_FUNCTION_ARGS)
 	}
 
 	/* Now construct the output string */
-	retval = (char *) palloc(overall_length);
+	retval = palloc_array(char, overall_length);
 	p = retval;
 
 #define APPENDSTR(str)	(strcpy(p, (str)), p += strlen(p))
@@ -1397,8 +1397,8 @@ array_recv(PG_FUNCTION_ARGS)
 	typalign = my_extra->typalign;
 	typioparam = my_extra->typioparam;
 
-	dataPtr = (Datum *) palloc(nitems * sizeof(Datum));
-	nullsPtr = (bool *) palloc(nitems * sizeof(bool));
+	dataPtr = palloc_array(Datum, nitems);
+	nullsPtr = palloc_array(bool, nitems);
 	ReadArrayBinary(buf, nitems,
 					&my_extra->proc, typioparam, typmod,
 					typlen, typbyval, typalign,
@@ -2259,7 +2259,7 @@ array_set_element(Datum arraydatum,
 					(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
 					 errmsg("cannot assign null value to an element of a fixed-length array")));
 
-		resultarray = (char *) palloc(arraytyplen);
+		resultarray = palloc_array(char, arraytyplen);
 		memcpy(resultarray, DatumGetPointer(arraydatum), arraytyplen);
 		elt_ptr = resultarray + indx[0] * elmlen;
 		ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalignby, elt_ptr);
@@ -3278,8 +3278,8 @@ array_map(Datum arrayd,
 	typalignby = typalign_to_alignby(typalign);
 
 	/* Allocate temporary arrays for new values */
-	values = (Datum *) palloc(nitems * sizeof(Datum));
-	nulls = (bool *) palloc(nitems * sizeof(bool));
+	values = palloc_array(Datum, nitems);
+	nulls = palloc_array(bool, nitems);
 
 	/* Loop over source data */
 	array_iter_setup(&iter, v, inp_typlen, inp_typbyval, inp_typalign);
@@ -4663,10 +4663,8 @@ array_create_iterator(ArrayType *arr, int slice_ndim, ArrayMetaState *mstate)
 		/*
 		 * Create workspace for building sub-arrays.
 		 */
-		iterator->slice_values = (Datum *)
-			palloc(iterator->slice_len * sizeof(Datum));
-		iterator->slice_nulls = (bool *)
-			palloc(iterator->slice_len * sizeof(bool));
+		iterator->slice_values = palloc_array(Datum, iterator->slice_len);
+		iterator->slice_nulls = palloc_array(bool, iterator->slice_len);
 	}
 
 	/*
@@ -5641,7 +5639,7 @@ accumArrayResultArr(ArrayBuildStateArr *astate,
 
 		/* Allocate at least enough data space for this item */
 		astate->abytes = pg_nextpower2_32(Max(1024, ndatabytes + 1));
-		astate->data = (char *) palloc(astate->abytes);
+		astate->data = palloc_array(char, astate->abytes);
 	}
 	else
 	{
@@ -5686,7 +5684,7 @@ accumArrayResultArr(ArrayBuildStateArr *astate,
 			 * previous inputs by marking all their items non-null.
 			 */
 			astate->aitems = pg_nextpower2_32(Max(256, newnitems + 1));
-			astate->nullbitmap = (uint8 *) palloc((astate->aitems + 7) / 8);
+			astate->nullbitmap = palloc_array(uint8, (astate->aitems + 7) / 8);
 			array_bitmap_copy(astate->nullbitmap, 0,
 							  NULL, 0,
 							  astate->nitems);
@@ -6489,8 +6487,8 @@ array_replace_internal(ArrayType *array,
 							 collation, NULL, NULL);
 
 	/* Allocate temporary arrays for new values */
-	values = (Datum *) palloc(nitems * sizeof(Datum));
-	nulls = (bool *) palloc(nitems * sizeof(bool));
+	values = palloc_array(Datum, nitems);
+	nulls = palloc_array(bool, nitems);
 
 	/* Loop over source data */
 	arraydataptr = ARR_DATA_PTR(array);
diff --git a/src/backend/utils/adt/arrayutils.c b/src/backend/utils/adt/arrayutils.c
index ca861a42037..2ad26f9b381 100644
--- a/src/backend/utils/adt/arrayutils.c
+++ b/src/backend/utils/adt/arrayutils.c
@@ -253,7 +253,7 @@ ArrayGetIntegerTypmods(ArrayType *arr, int *n)
 
 	deconstruct_array_builtin(arr, CSTRINGOID, &elem_values, NULL, n);
 
-	result = (int32 *) palloc(*n * sizeof(int32));
+	result = palloc_array(int32, *n);
 
 	for (i = 0; i < *n; i++)
 		result[i] = pg_strtoint32(DatumGetCString(elem_values[i]));
diff --git a/src/backend/utils/adt/bool.c b/src/backend/utils/adt/bool.c
index 090ad7df9ca..390b5aafd8d 100644
--- a/src/backend/utils/adt/bool.c
+++ b/src/backend/utils/adt/bool.c
@@ -158,7 +158,7 @@ Datum
 boolout(PG_FUNCTION_ARGS)
 {
 	bool		b = PG_GETARG_BOOL(0);
-	char	   *result = (char *) palloc(2);
+	char	   *result = palloc_array(char, 2);
 
 	result[0] = (b) ? 't' : 'f';
 	result[1] = '\0';
diff --git a/src/backend/utils/adt/bytea.c b/src/backend/utils/adt/bytea.c
index a1f5d4e572b..eb27054b4f4 100644
--- a/src/backend/utils/adt/bytea.c
+++ b/src/backend/utils/adt/bytea.c
@@ -314,7 +314,7 @@ byteaout(PG_FUNCTION_ARGS)
 			ereport(ERROR,
 					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 					 errmsg_internal("result of bytea output conversion is too large")));
-		rp = result = (char *) palloc(len);
+		rp = result = palloc_array(char, len);
 
 		vp = VARDATA_ANY(vlena);
 		for (i = VARSIZE_ANY_EXHDR(vlena); i != 0; i--, vp++)
diff --git a/src/backend/utils/adt/char.c b/src/backend/utils/adt/char.c
index 698863924ee..e74fdfed852 100644
--- a/src/backend/utils/adt/char.c
+++ b/src/backend/utils/adt/char.c
@@ -64,7 +64,7 @@ Datum
 charout(PG_FUNCTION_ARGS)
 {
 	char		ch = PG_GETARG_CHAR(0);
-	char	   *result = (char *) palloc(5);
+	char	   *result = palloc_array(char, 5);
 
 	if (IS_HIGHBIT_SET(ch))
 	{
diff --git a/src/backend/utils/adt/datum.c b/src/backend/utils/adt/datum.c
index 1d622e31a83..39a32eb9d9c 100644
--- a/src/backend/utils/adt/datum.c
+++ b/src/backend/utils/adt/datum.c
@@ -148,7 +148,7 @@ datumCopy(Datum value, bool typByVal, int typLen)
 			char	   *resultptr;
 
 			resultsize = EOH_get_flat_size(eoh);
-			resultptr = (char *) palloc(resultsize);
+			resultptr = palloc_array(char, resultsize);
 			EOH_flatten_into(eoh, resultptr, resultsize);
 			res = PointerGetDatum(resultptr);
 		}
@@ -159,7 +159,7 @@ datumCopy(Datum value, bool typByVal, int typLen)
 			char	   *resultptr;
 
 			realSize = (Size) VARSIZE_ANY(vl);
-			resultptr = (char *) palloc(realSize);
+			resultptr = palloc_array(char, realSize);
 			memcpy(resultptr, vl, realSize);
 			res = PointerGetDatum(resultptr);
 		}
@@ -172,7 +172,7 @@ datumCopy(Datum value, bool typByVal, int typLen)
 
 		realSize = datumGetSize(value, typByVal, typLen);
 
-		resultptr = (char *) palloc(realSize);
+		resultptr = palloc_array(char, realSize);
 		memcpy(resultptr, DatumGetPointer(value), realSize);
 		res = PointerGetDatum(resultptr);
 	}
@@ -532,7 +532,7 @@ datumSerialize(Datum value, bool isnull, bool typByVal, int typLen,
 			 * EOH_flatten_into expects the target address to be maxaligned,
 			 * so we can't store directly to *start_address.
 			 */
-			tmp = (char *) palloc(header);
+			tmp = palloc_array(char, header);
 			EOH_flatten_into(eoh, tmp, header);
 			memcpy(*start_address, tmp, header);
 			*start_address += header;
diff --git a/src/backend/utils/adt/enum.c b/src/backend/utils/adt/enum.c
index 286d4311ed5..5d6a3af9172 100644
--- a/src/backend/utils/adt/enum.c
+++ b/src/backend/utils/adt/enum.c
@@ -572,7 +572,7 @@ enum_range_internal(Oid enumtypoid, Oid lower, Oid upper)
 	enum_scan = systable_beginscan_ordered(enum_rel, enum_idx, NULL, 1, &skey);
 
 	max = 64;
-	elems = (Datum *) palloc(max * sizeof(Datum));
+	elems = palloc_array(Datum, max);
 	cnt = 0;
 	left_found = !OidIsValid(lower);
 
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index 4c2ccdfbf3f..71148526c6b 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -360,7 +360,7 @@ Datum
 float4out(PG_FUNCTION_ARGS)
 {
 	float4		num = PG_GETARG_FLOAT4(0);
-	char	   *ascii = (char *) palloc(32);
+	char	   *ascii = palloc_array(char, 32);
 	int			ndig = FLT_DIG + extra_float_digits;
 
 	if (extra_float_digits > 0)
@@ -577,7 +577,7 @@ float8out(PG_FUNCTION_ARGS)
 char *
 float8out_internal(double num)
 {
-	char	   *ascii = (char *) palloc(32);
+	char	   *ascii = palloc_array(char, 32);
 	int			ndig = DBL_DIG + extra_float_digits;
 
 	if (extra_float_digits > 0)
diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c
index 7a5695c6245..366e54fd1ca 100644
--- a/src/backend/utils/adt/format_type.c
+++ b/src/backend/utils/adt/format_type.c
@@ -458,7 +458,7 @@ oidvectortypes(PG_FUNCTION_ARGS)
 	numargs = oidArray->dim1;
 
 	total = 20 * numargs + 1;
-	result = palloc(total);
+	result = palloc_array(char, total);
 	result[0] = '\0';
 	left = total - 1;
 
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 641b7aa679e..462e36e4887 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -1656,7 +1656,7 @@ str_tolower(const char *buff, size_t nbytes, Oid collid)
 
 		/* first try buffer of equal size plus terminating NUL */
 		dstsize = srclen + 1;
-		dst = palloc(dstsize);
+		dst = palloc_array(char, dstsize);
 
 		needed = pg_strlower(dst, dstsize, src, srclen, mylocale);
 		if (needed + 1 > dstsize)
@@ -1720,7 +1720,7 @@ str_toupper(const char *buff, size_t nbytes, Oid collid)
 
 		/* first try buffer of equal size plus terminating NUL */
 		dstsize = srclen + 1;
-		dst = palloc(dstsize);
+		dst = palloc_array(char, dstsize);
 
 		needed = pg_strupper(dst, dstsize, src, srclen, mylocale);
 		if (needed + 1 > dstsize)
@@ -1784,7 +1784,7 @@ str_initcap(const char *buff, size_t nbytes, Oid collid)
 
 		/* first try buffer of equal size plus terminating NUL */
 		dstsize = srclen + 1;
-		dst = palloc(dstsize);
+		dst = palloc_array(char, dstsize);
 
 		needed = pg_strtitle(dst, dstsize, src, srclen, mylocale);
 		if (needed + 1 > dstsize)
@@ -1853,7 +1853,7 @@ str_casefold(const char *buff, size_t nbytes, Oid collid)
 
 		/* first try buffer of equal size plus terminating NUL */
 		dstsize = srclen + 1;
-		dst = palloc(dstsize);
+		dst = palloc_array(char, dstsize);
 
 		needed = pg_strfold(dst, dstsize, src, srclen, mylocale);
 		if (needed + 1 > dstsize)
@@ -5122,7 +5122,7 @@ int_to_roman(int number)
 	char	   *result,
 				numstr[12];
 
-	result = (char *) palloc(MAX_ROMAN_LEN + 1);
+	result = palloc_array(char, MAX_ROMAN_LEN + 1);
 	*result = '\0';
 
 	/*
@@ -6395,7 +6395,7 @@ numeric_to_number(PG_FUNCTION_ARGS)
 
 	format = NUM_cache(len, &Num, fmt, &shouldFree);
 
-	numstr = (char *) palloc((len * NUM_MAX_ITEM_SIZ) + 1);
+	numstr = palloc_array(char, (len * NUM_MAX_ITEM_SIZ) + 1);
 
 	NUM_processor(format, &Num, VARDATA_ANY(value), numstr,
 				  VARSIZE_ANY_EXHDR(value), 0, 0, false, PG_GET_COLLATION());
@@ -6482,14 +6482,14 @@ numeric_to_char(PG_FUNCTION_ARGS)
 			 * Allow 6 characters for the leading sign, the decimal point,
 			 * "e", the exponent's sign and two exponent digits.
 			 */
-			numstr = (char *) palloc(Num.pre + Num.post + 7);
+			numstr = palloc_array(char, Num.pre + Num.post + 7);
 			fill_str(numstr, '#', Num.pre + Num.post + 6);
 			*numstr = ' ';
 			*(numstr + Num.pre + 1) = '.';
 		}
 		else if (*orgnum != '-')
 		{
-			numstr = (char *) palloc(strlen(orgnum) + 2);
+			numstr = palloc_array(char, strlen(orgnum) + 2);
 			*numstr = ' ';
 			strcpy(numstr + 1, orgnum);
 		}
@@ -6546,7 +6546,7 @@ numeric_to_char(PG_FUNCTION_ARGS)
 		/* overflowed prefix digit format? */
 		else if (numstr_pre_len > Num.pre)
 		{
-			numstr = (char *) palloc(Num.pre + Num.post + 2);
+			numstr = palloc_array(char, Num.pre + Num.post + 2);
 			fill_str(numstr, '#', Num.pre + Num.post + 1);
 			*(numstr + Num.pre) = '.';
 		}
@@ -6624,7 +6624,7 @@ int4_to_char(PG_FUNCTION_ARGS)
 		/* post-decimal digits?  Pad out with zeros. */
 		if (Num.post)
 		{
-			numstr = (char *) palloc(numstr_pre_len + Num.post + 2);
+			numstr = palloc_array(char, numstr_pre_len + Num.post + 2);
 			strcpy(numstr, orgnum);
 			*(numstr + numstr_pre_len) = '.';
 			memset(numstr + numstr_pre_len + 1, '0', Num.post);
@@ -6639,7 +6639,7 @@ int4_to_char(PG_FUNCTION_ARGS)
 		/* overflowed prefix digit format? */
 		else if (numstr_pre_len > Num.pre)
 		{
-			numstr = (char *) palloc(Num.pre + Num.post + 2);
+			numstr = palloc_array(char, Num.pre + Num.post + 2);
 			fill_str(numstr, '#', Num.pre + Num.post + 1);
 			*(numstr + Num.pre) = '.';
 		}
@@ -6695,7 +6695,7 @@ int8_to_char(PG_FUNCTION_ARGS)
 		 */
 		if (*orgnum != '-')
 		{
-			numstr = (char *) palloc(strlen(orgnum) + 2);
+			numstr = palloc_array(char, strlen(orgnum) + 2);
 			*numstr = ' ';
 			strcpy(numstr + 1, orgnum);
 		}
@@ -6735,7 +6735,7 @@ int8_to_char(PG_FUNCTION_ARGS)
 		/* post-decimal digits?  Pad out with zeros. */
 		if (Num.post)
 		{
-			numstr = (char *) palloc(numstr_pre_len + Num.post + 2);
+			numstr = palloc_array(char, numstr_pre_len + Num.post + 2);
 			strcpy(numstr, orgnum);
 			*(numstr + numstr_pre_len) = '.';
 			memset(numstr + numstr_pre_len + 1, '0', Num.post);
@@ -6750,7 +6750,7 @@ int8_to_char(PG_FUNCTION_ARGS)
 		/* overflowed prefix digit format? */
 		else if (numstr_pre_len > Num.pre)
 		{
-			numstr = (char *) palloc(Num.pre + Num.post + 2);
+			numstr = palloc_array(char, Num.pre + Num.post + 2);
 			fill_str(numstr, '#', Num.pre + Num.post + 1);
 			*(numstr + Num.pre) = '.';
 		}
@@ -6800,7 +6800,7 @@ float4_to_char(PG_FUNCTION_ARGS)
 			 * Allow 6 characters for the leading sign, the decimal point,
 			 * "e", the exponent's sign and two exponent digits.
 			 */
-			numstr = (char *) palloc(Num.pre + Num.post + 7);
+			numstr = palloc_array(char, Num.pre + Num.post + 7);
 			fill_str(numstr, '#', Num.pre + Num.post + 6);
 			*numstr = ' ';
 			*(numstr + Num.pre + 1) = '.';
@@ -6862,7 +6862,7 @@ float4_to_char(PG_FUNCTION_ARGS)
 		/* overflowed prefix digit format? */
 		else if (numstr_pre_len > Num.pre)
 		{
-			numstr = (char *) palloc(Num.pre + Num.post + 2);
+			numstr = palloc_array(char, Num.pre + Num.post + 2);
 			fill_str(numstr, '#', Num.pre + Num.post + 1);
 			*(numstr + Num.pre) = '.';
 		}
@@ -6912,7 +6912,7 @@ float8_to_char(PG_FUNCTION_ARGS)
 			 * Allow 6 characters for the leading sign, the decimal point,
 			 * "e", the exponent's sign and two exponent digits.
 			 */
-			numstr = (char *) palloc(Num.pre + Num.post + 7);
+			numstr = palloc_array(char, Num.pre + Num.post + 7);
 			fill_str(numstr, '#', Num.pre + Num.post + 6);
 			*numstr = ' ';
 			*(numstr + Num.pre + 1) = '.';
@@ -6974,7 +6974,7 @@ float8_to_char(PG_FUNCTION_ARGS)
 		/* overflowed prefix digit format? */
 		else if (numstr_pre_len > Num.pre)
 		{
-			numstr = (char *) palloc(Num.pre + Num.post + 2);
+			numstr = palloc_array(char, Num.pre + Num.post + 2);
 			fill_str(numstr, '#', Num.pre + Num.post + 1);
 			*(numstr + Num.pre) = '.';
 		}
diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index 01608d8ca42..da1e3b7844f 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -74,7 +74,7 @@ Datum
 int2out(PG_FUNCTION_ARGS)
 {
 	int16		arg1 = PG_GETARG_INT16(0);
-	char	   *result = (char *) palloc(7);	/* sign, 5 digits, '\0' */
+	char	   *result = palloc_array(char, 7); /* sign, 5 digits, '\0' */
 
 	pg_itoa(arg1, result);
 	PG_RETURN_CSTRING(result);
@@ -241,7 +241,7 @@ int2vectorout(PG_FUNCTION_ARGS)
 	nnums = int2Array->dim1;
 
 	/* assumes sign, 5 digits, ' ' */
-	rp = result = (char *) palloc(nnums * 7 + 1);
+	rp = result = palloc_array(char, nnums * 7 + 1);
 	for (num = 0; num < nnums; num++)
 	{
 		if (num != 0)
@@ -327,7 +327,7 @@ Datum
 int4out(PG_FUNCTION_ARGS)
 {
 	int32		arg1 = PG_GETARG_INT32(0);
-	char	   *result = (char *) palloc(12);	/* sign, 10 digits, '\0' */
+	char	   *result = palloc_array(char, 12);	/* sign, 10 digits, '\0' */
 
 	pg_ltoa(arg1, result);
 	PG_RETURN_CSTRING(result);
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c
index 97cc3d60340..a1fa55fa2dd 100644
--- a/src/backend/utils/adt/jsonfuncs.c
+++ b/src/backend/utils/adt/jsonfuncs.c
@@ -613,7 +613,7 @@ jsonb_object_keys(PG_FUNCTION_ARGS)
 			{
 				char	   *cstr;
 
-				cstr = palloc(v.val.string.len + 1 * sizeof(char));
+				cstr = palloc_array(char, v.val.string.len + 1);
 				memcpy(cstr, v.val.string.val, v.val.string.len);
 				cstr[v.val.string.len] = '\0';
 				state->result[state->result_count++] = cstr;
@@ -3555,8 +3555,8 @@ populate_record(TupleDesc tupdesc,
 		record->ncolumns = ncolumns;
 	}
 
-	values = (Datum *) palloc(ncolumns * sizeof(Datum));
-	nulls = (bool *) palloc(ncolumns * sizeof(bool));
+	values = palloc_array(Datum, ncolumns);
+	nulls = palloc_array(bool, ncolumns);
 
 	if (defaultval)
 	{
@@ -3911,7 +3911,7 @@ hash_object_field_end(void *state, char *fname, bool isnull)
 	if (_state->save_json_start != NULL)
 	{
 		int			len = _state->lex->prev_token_terminator - _state->save_json_start;
-		char	   *val = palloc((len + 1) * sizeof(char));
+		char	   *val = palloc_array(char, len + 1);
 
 		memcpy(val, _state->save_json_start, len);
 		val[len] = '\0';
@@ -4362,7 +4362,7 @@ populate_recordset_object_field_end(void *state, char *fname, bool isnull)
 	if (_state->save_json_start != NULL)
 	{
 		int			len = _state->lex->prev_token_terminator - _state->save_json_start;
-		char	   *val = palloc((len + 1) * sizeof(char));
+		char	   *val = palloc_array(char, len + 1);
 
 		memcpy(val, _state->save_json_start, len);
 		val[len] = '\0';
diff --git a/src/backend/utils/adt/jsonpath_scan.l b/src/backend/utils/adt/jsonpath_scan.l
index e4fadcc2e69..50017587ecb 100644
--- a/src/backend/utils/adt/jsonpath_scan.l
+++ b/src/backend/utils/adt/jsonpath_scan.l
@@ -498,7 +498,7 @@ resizeString(bool init, int appendLen, yyscan_t yyscanner)
 	if (init)
 	{
 		yyextra->scanstring.total = Max(32, appendLen);
-		yyextra->scanstring.val = (char *) palloc(yyextra->scanstring.total);
+		yyextra->scanstring.val = palloc_array(char, yyextra->scanstring.total);
 		yyextra->scanstring.len = 0;
 	}
 	else
diff --git a/src/backend/utils/adt/levenshtein.c b/src/backend/utils/adt/levenshtein.c
index 5b3d84029f6..18f2c3bfb4f 100644
--- a/src/backend/utils/adt/levenshtein.c
+++ b/src/backend/utils/adt/levenshtein.c
@@ -197,7 +197,7 @@ varstr_levenshtein(const char *source, int slen,
 		int			i;
 		const char *cp = source;
 
-		s_char_len = (int *) palloc((m + 1) * sizeof(int));
+		s_char_len = palloc_array(int, m + 1);
 		for (i = 0; i < m; ++i)
 		{
 			s_char_len[i] = pg_mblen_range(cp, send);
@@ -211,7 +211,7 @@ varstr_levenshtein(const char *source, int slen,
 	++n;
 
 	/* Previous and current rows of notional array. */
-	prev = (int *) palloc(2 * m * sizeof(int));
+	prev = palloc_array(int, 2 * m);
 	curr = prev + m;
 
 	/*
diff --git a/src/backend/utils/adt/like_support.c b/src/backend/utils/adt/like_support.c
index e354360a8e6..804ad64d3fb 100644
--- a/src/backend/utils/adt/like_support.c
+++ b/src/backend/utils/adt/like_support.c
@@ -1019,7 +1019,7 @@ like_fixed_prefix(Const *patt_const, Const **prefix_const,
 		bytea	   *bstr = DatumGetByteaPP(patt_const->constvalue);
 
 		pattlen = VARSIZE_ANY_EXHDR(bstr);
-		patt = (char *) palloc(pattlen);
+		patt = palloc_array(char, pattlen);
 		memcpy(patt, VARDATA_ANY(bstr), pattlen);
 		Assert(bstr == DatumGetPointer(patt_const->constvalue));
 	}
@@ -1109,10 +1109,10 @@ like_fixed_prefix_ci(Const *patt_const, Oid collation, Const **prefix_const,
 
 	locale = pg_newlocale_from_collation(collation);
 
-	wpatt = palloc((nbytes + 1) * sizeof(pg_wchar));
+	wpatt = palloc_array(pg_wchar, nbytes + 1);
 	wpattlen = pg_mb2wchar_with_len(VARDATA_ANY(val), wpatt, nbytes);
 
-	wmatch = palloc((nbytes + 1) * sizeof(pg_wchar));
+	wmatch = palloc_array(pg_wchar, nbytes + 1);
 	for (wpos = 0; wpos < wpattlen; wpos++)
 	{
 		/* % and _ are wildcard characters in LIKE */
@@ -1642,7 +1642,7 @@ make_greater_string(const Const *str_const, FmgrInfo *ltproc, Oid collation)
 		bytea	   *bstr = DatumGetByteaPP(str_const->constvalue);
 
 		len = VARSIZE_ANY_EXHDR(bstr);
-		workstr = (char *) palloc(len);
+		workstr = palloc_array(char, len);
 		memcpy(workstr, VARDATA_ANY(bstr), len);
 		Assert(bstr == DatumGetPointer(str_const->constvalue));
 		cmpstr = str_const->constvalue;
diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c
index 8e9f160db97..3eb9a5b4215 100644
--- a/src/backend/utils/adt/lockfuncs.c
+++ b/src/backend/utils/adt/lockfuncs.c
@@ -477,7 +477,7 @@ pg_blocking_pids(PG_FUNCTION_ARGS)
 	lockData = GetBlockerStatusData(blocked_pid);
 
 	/* We can't need more output entries than there are reported PROCLOCKs */
-	arrayelems = (Datum *) palloc(lockData->nlocks * sizeof(Datum));
+	arrayelems = palloc_array(Datum, lockData->nlocks);
 	narrayelems = 0;
 
 	/* For each blocked proc in the lock group ... */
@@ -579,7 +579,7 @@ pg_safe_snapshot_blocking_pids(PG_FUNCTION_ARGS)
 	Datum	   *blocker_datums;
 
 	/* A buffer big enough for any possible blocker list without truncation */
-	blockers = (int *) palloc(MaxBackends * sizeof(int));
+	blockers = palloc_array(int, MaxBackends);
 
 	/* Collect a snapshot of processes waited for by GetSafeSnapshot */
 	num_blockers =
@@ -590,7 +590,7 @@ pg_safe_snapshot_blocking_pids(PG_FUNCTION_ARGS)
 	{
 		int			i;
 
-		blocker_datums = (Datum *) palloc(num_blockers * sizeof(Datum));
+		blocker_datums = palloc_array(Datum, num_blockers);
 		for (i = 0; i < num_blockers; ++i)
 			blocker_datums[i] = Int32GetDatum(blockers[i]);
 	}
diff --git a/src/backend/utils/adt/mac.c b/src/backend/utils/adt/mac.c
index 923c5af54f8..f8fc607dd02 100644
--- a/src/backend/utils/adt/mac.c
+++ b/src/backend/utils/adt/mac.c
@@ -112,7 +112,7 @@ macaddr_out(PG_FUNCTION_ARGS)
 	macaddr    *addr = PG_GETARG_MACADDR_P(0);
 	char	   *result;
 
-	result = (char *) palloc(32);
+	result = palloc_array(char, 32);
 
 	snprintf(result, 32, "%02x:%02x:%02x:%02x:%02x:%02x",
 			 addr->a, addr->b, addr->c, addr->d, addr->e, addr->f);
diff --git a/src/backend/utils/adt/mac8.c b/src/backend/utils/adt/mac8.c
index 0425ea473a5..c6321f161a0 100644
--- a/src/backend/utils/adt/mac8.c
+++ b/src/backend/utils/adt/mac8.c
@@ -236,7 +236,7 @@ macaddr8_out(PG_FUNCTION_ARGS)
 	macaddr8   *addr = PG_GETARG_MACADDR8_P(0);
 	char	   *result;
 
-	result = (char *) palloc(32);
+	result = palloc_array(char, 32);
 
 	snprintf(result, 32, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
 			 addr->a, addr->b, addr->c, addr->d,
diff --git a/src/backend/utils/adt/multirangetypes.c b/src/backend/utils/adt/multirangetypes.c
index c62a5e755ea..ccb9ba2b644 100644
--- a/src/backend/utils/adt/multirangetypes.c
+++ b/src/backend/utils/adt/multirangetypes.c
@@ -1004,7 +1004,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 = palloc0_array(RangeType *, range_count);
 		for (i = 0; i < range_count; i++)
 		{
 			if (nulls[i])
@@ -1108,7 +1108,7 @@ multirange_union(PG_FUNCTION_ARGS)
 	multirange_deserialize(typcache->rngtype, mr2, &range_count2, &ranges2);
 
 	range_count3 = range_count1 + range_count2;
-	ranges3 = palloc0(range_count3 * sizeof(RangeType *));
+	ranges3 = palloc0_array(RangeType *, range_count3);
 	memcpy(ranges3, ranges1, range_count1 * sizeof(RangeType *));
 	memcpy(ranges3 + range_count1, ranges2, range_count2 * sizeof(RangeType *));
 	PG_RETURN_MULTIRANGE_P(make_multirange(typcache->type_id, typcache->rngtype,
@@ -1162,7 +1162,7 @@ multirange_minus_internal(Oid mltrngtypoid, TypeCacheEntry *rangetyp,
 	 * Worst case: every range in ranges1 makes a different cut to some range
 	 * in ranges2.
 	 */
-	ranges3 = palloc0((range_count1 + range_count2) * sizeof(RangeType *));
+	ranges3 = palloc0_array(RangeType *, range_count1 + range_count2);
 	range_count3 = 0;
 
 	/*
@@ -1359,7 +1359,7 @@ multirange_intersect_internal(Oid mltrngtypoid, TypeCacheEntry *rangetyp,
 	 * but one extra won't hurt.
 	 *-----------------------------------------------
 	 */
-	ranges3 = palloc0((range_count1 + range_count2) * sizeof(RangeType *));
+	ranges3 = palloc0_array(RangeType *, range_count1 + range_count2);
 	range_count3 = 0;
 
 	/*
@@ -1472,7 +1472,7 @@ range_agg_finalfn(PG_FUNCTION_ARGS)
 	mltrngtypoid = get_fn_expr_rettype(fcinfo->flinfo);
 	typcache = multirange_get_typcache(fcinfo, mltrngtypoid);
 
-	ranges = palloc0(range_count * sizeof(RangeType *));
+	ranges = palloc0_array(RangeType *, range_count);
 	for (i = 0; i < range_count; i++)
 		ranges[i] = DatumGetRangeTypeP(state->dvalues[i]);
 
diff --git a/src/backend/utils/adt/name.c b/src/backend/utils/adt/name.c
index 4e9131a0b20..cbd1808bb5c 100644
--- a/src/backend/utils/adt/name.c
+++ b/src/backend/utils/adt/name.c
@@ -299,7 +299,7 @@ current_schemas(PG_FUNCTION_ARGS)
 	int			i;
 	ArrayType  *array;
 
-	names = (Datum *) palloc(list_length(search_path) * sizeof(Datum));
+	names = palloc_array(Datum, list_length(search_path));
 	i = 0;
 	foreach(l, search_path)
 	{
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index c9717faea26..3e7043e90bb 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -476,7 +476,7 @@ static void dump_var(const char *str, NumericVar *var);
 #endif
 
 #define digitbuf_alloc(ndigits)  \
-	((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
+	(palloc_array(NumericDigit, (ndigits)))
 #define digitbuf_free(buf)	\
 	do { \
 		 if ((buf) != NULL) \
@@ -1360,7 +1360,7 @@ Datum
 numerictypmodout(PG_FUNCTION_ARGS)
 {
 	int32		typmod = PG_GETARG_INT32(0);
-	char	   *res = (char *) palloc(64);
+	char	   *res = palloc_array(char, 64);
 
 	if (is_valid_numeric_typmod(typmod))
 		snprintf(res, 64, "(%d,%d)",
@@ -12052,8 +12052,8 @@ accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
 
 		weightdiff = accum_weight - old_weight;
 
-		new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
-		new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
+		new_pos_digits = palloc0_array(int32, accum_ndigits);
+		new_neg_digits = palloc0_array(int32, accum_ndigits);
 
 		if (accum->pos_digits)
 		{
@@ -12141,8 +12141,8 @@ accum_sum_final(NumericSumAccum *accum, NumericVar *result)
 static void
 accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src)
 {
-	dst->pos_digits = palloc(src->ndigits * sizeof(int32));
-	dst->neg_digits = palloc(src->ndigits * sizeof(int32));
+	dst->pos_digits = palloc_array(int32, src->ndigits);
+	dst->neg_digits = palloc_array(int32, src->ndigits);
 
 	memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
 	memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c
index a3419728971..c1caaaeebcc 100644
--- a/src/backend/utils/adt/oid.c
+++ b/src/backend/utils/adt/oid.c
@@ -47,7 +47,7 @@ Datum
 oidout(PG_FUNCTION_ARGS)
 {
 	Oid			o = PG_GETARG_OID(0);
-	char	   *result = (char *) palloc(12);
+	char	   *result = palloc_array(char, 12);
 
 	snprintf(result, 12, "%u", o);
 	PG_RETURN_CSTRING(result);
@@ -192,7 +192,7 @@ oidvectorout(PG_FUNCTION_ARGS)
 	nnums = oidArray->dim1;
 
 	/* assumes sign, 10 digits, ' ' */
-	rp = result = (char *) palloc(nnums * 12 + 1);
+	rp = result = palloc_array(char, nnums * 12 + 1);
 	for (num = 0; num < nnums; num++)
 	{
 		if (num != 0)
diff --git a/src/backend/utils/adt/oracle_compat.c b/src/backend/utils/adt/oracle_compat.c
index 5b0d098bd07..3af8224e6c8 100644
--- a/src/backend/utils/adt/oracle_compat.c
+++ b/src/backend/utils/adt/oracle_compat.c
@@ -424,8 +424,8 @@ dotrim(const char *string, int stringlen,
 			const char *str_pos;
 			int			str_len;
 
-			stringchars = (const char **) palloc(stringlen * sizeof(char *));
-			stringmblen = (int *) palloc(stringlen * sizeof(int));
+			stringchars = palloc_array(const char *, stringlen);
+			stringmblen = palloc_array(int, stringlen);
 			stringnchars = 0;
 			p = string;
 			len = stringlen;
@@ -439,8 +439,8 @@ dotrim(const char *string, int stringlen,
 				len -= mblen;
 			}
 
-			setchars = (const char **) palloc(setlen * sizeof(char *));
-			setmblen = (int *) palloc(setlen * sizeof(int));
+			setchars = palloc_array(const char *, setlen);
+			setmblen = palloc_array(int, setlen);
 			setnchars = 0;
 			p = set;
 			len = setlen;
diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c
index fd8b8676470..657fc4969a1 100644
--- a/src/backend/utils/adt/orderedsetaggs.c
+++ b/src/backend/utils/adt/orderedsetaggs.c
@@ -173,11 +173,11 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
 			if (ishypothetical)
 				numSortCols++;	/* make space for flag column */
 			qstate->numSortCols = numSortCols;
-			qstate->sortColIdx = (AttrNumber *) palloc(numSortCols * sizeof(AttrNumber));
-			qstate->sortOperators = (Oid *) palloc(numSortCols * sizeof(Oid));
-			qstate->eqOperators = (Oid *) palloc(numSortCols * sizeof(Oid));
-			qstate->sortCollations = (Oid *) palloc(numSortCols * sizeof(Oid));
-			qstate->sortNullsFirsts = (bool *) palloc(numSortCols * sizeof(bool));
+			qstate->sortColIdx = palloc_array(AttrNumber, numSortCols);
+			qstate->sortOperators = palloc_array(Oid, numSortCols);
+			qstate->eqOperators = palloc_array(Oid, numSortCols);
+			qstate->sortCollations = palloc_array(Oid, numSortCols);
+			qstate->sortNullsFirsts = palloc_array(bool, numSortCols);
 
 			i = 0;
 			foreach(lc, sortlist)
@@ -669,7 +669,7 @@ setup_pct_info(int num_percentiles,
 	struct pct_info *pct_info;
 	int			i;
 
-	pct_info = (struct pct_info *) palloc(num_percentiles * sizeof(struct pct_info));
+	pct_info = palloc_array(struct pct_info, num_percentiles);
 
 	for (i = 0; i < num_percentiles; i++)
 	{
@@ -775,8 +775,8 @@ percentile_disc_multi_final(PG_FUNCTION_ARGS)
 							  osastate->number_of_rows,
 							  false);
 
-	result_datum = (Datum *) palloc(num_percentiles * sizeof(Datum));
-	result_isnull = (bool *) palloc(num_percentiles * sizeof(bool));
+	result_datum = palloc_array(Datum, num_percentiles);
+	result_isnull = palloc_array(bool, num_percentiles);
 
 	/*
 	 * Start by dealing with any nulls in the param array - those are sorted
@@ -898,8 +898,8 @@ percentile_cont_multi_final_common(FunctionCallInfo fcinfo,
 							  osastate->number_of_rows,
 							  true);
 
-	result_datum = (Datum *) palloc(num_percentiles * sizeof(Datum));
-	result_isnull = (bool *) palloc(num_percentiles * sizeof(bool));
+	result_datum = palloc_array(Datum, num_percentiles);
+	result_isnull = palloc_array(bool, num_percentiles);
 
 	/*
 	 * Start by dealing with any nulls in the param array - those are sorted
diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c
index 9eb99487e57..fb69320d2c9 100644
--- a/src/backend/utils/adt/pg_locale.c
+++ b/src/backend/utils/adt/pg_locale.c
@@ -1742,7 +1742,7 @@ icu_language_tag(const char *loc_str, int elevel)
 	 * uloc_toLanguageTag() doesn't always return the ultimate length on the
 	 * first call, necessitating a loop.
 	 */
-	langtag = palloc(buflen);
+	langtag = palloc_array(char, buflen);
 	while (true)
 	{
 		status = U_ZERO_ERROR;
diff --git a/src/backend/utils/adt/pg_ndistinct.c b/src/backend/utils/adt/pg_ndistinct.c
index 2cdc8ebb912..52a9eea6a59 100644
--- a/src/backend/utils/adt/pg_ndistinct.c
+++ b/src/backend/utils/adt/pg_ndistinct.c
@@ -177,7 +177,7 @@ ndistinct_object_end(void *state)
 	/* Create the MVNDistinctItem */
 	item = palloc_object(MVNDistinctItem);
 	item->nattributes = natts;
-	item->attributes = palloc0(natts * sizeof(AttrNumber));
+	item->attributes = palloc0_array(AttrNumber, natts);
 	item->ndistinct = (double) parse->ndistinct;
 
 	for (int i = 0; i < natts; i++)
diff --git a/src/backend/utils/adt/rangetypes_typanalyze.c b/src/backend/utils/adt/rangetypes_typanalyze.c
index 278d4e6941a..b152b1e86ae 100644
--- a/src/backend/utils/adt/rangetypes_typanalyze.c
+++ b/src/backend/utils/adt/rangetypes_typanalyze.c
@@ -288,7 +288,7 @@ compute_range_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
 			if (num_hist > num_bins)
 				num_hist = num_bins + 1;
 
-			bound_hist_values = (Datum *) palloc(num_hist * sizeof(Datum));
+			bound_hist_values = palloc_array(Datum, num_hist);
 
 			/*
 			 * The object of this loop is to construct ranges from first and
@@ -352,7 +352,7 @@ compute_range_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
 			if (num_hist > num_bins)
 				num_hist = num_bins + 1;
 
-			length_hist_values = (Datum *) palloc(num_hist * sizeof(Datum));
+			length_hist_values = palloc_array(Datum, num_hist);
 
 			/*
 			 * The object of this loop is to copy the first and last lengths[]
diff --git a/src/backend/utils/adt/regexp.c b/src/backend/utils/adt/regexp.c
index 311b9877bbb..371e5af28f1 100644
--- a/src/backend/utils/adt/regexp.c
+++ b/src/backend/utils/adt/regexp.c
@@ -2071,7 +2071,7 @@ regexp_fixed_prefix(text *text_re, bool case_insensitive, Oid collation,
 
 	/* Convert pg_wchar result back to database encoding */
 	maxlen = pg_database_encoding_max_length() * slen + 1;
-	result = (char *) palloc(maxlen);
+	result = palloc_array(char, maxlen);
 	slen = pg_wchar2mb_with_len(str, result, slen);
 	Assert(slen < maxlen);
 
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index 64f293f4e98..cfe2031c249 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -189,7 +189,7 @@ regprocout(PG_FUNCTION_ARGS)
 	else
 	{
 		/* If OID doesn't match any pg_proc entry, return it numerically */
-		result = (char *) palloc(NAMEDATALEN);
+		result = palloc_array(char, NAMEDATALEN);
 		snprintf(result, NAMEDATALEN, "%u", proid);
 	}
 
@@ -387,7 +387,7 @@ format_procedure_extended(Oid procedure_oid, uint16 flags)
 	else
 	{
 		/* If OID doesn't match any pg_proc entry, return it numerically */
-		result = (char *) palloc(NAMEDATALEN);
+		result = palloc_array(char, NAMEDATALEN);
 		snprintf(result, NAMEDATALEN, "%u", procedure_oid);
 	}
 
@@ -595,7 +595,7 @@ regoperout(PG_FUNCTION_ARGS)
 
 				nspname = get_namespace_name(operform->oprnamespace);
 				nspname = quote_identifier(nspname);
-				result = (char *) palloc(strlen(nspname) + strlen(oprname) + 2);
+				result = palloc_array(char, strlen(nspname) + strlen(oprname) + 2);
 				sprintf(result, "%s.%s", nspname, oprname);
 			}
 		}
@@ -607,7 +607,7 @@ regoperout(PG_FUNCTION_ARGS)
 		/*
 		 * If OID doesn't match any pg_operator entry, return it numerically
 		 */
-		result = (char *) palloc(NAMEDATALEN);
+		result = palloc_array(char, NAMEDATALEN);
 		snprintf(result, NAMEDATALEN, "%u", oprid);
 	}
 
@@ -790,7 +790,7 @@ format_operator_extended(Oid operator_oid, uint16 flags)
 		/*
 		 * If OID doesn't match any pg_operator entry, return it numerically
 		 */
-		result = (char *) palloc(NAMEDATALEN);
+		result = palloc_array(char, NAMEDATALEN);
 		snprintf(result, NAMEDATALEN, "%u", operator_oid);
 	}
 
@@ -994,7 +994,7 @@ regclassout(PG_FUNCTION_ARGS)
 	else
 	{
 		/* If OID doesn't match any pg_class entry, return it numerically */
-		result = (char *) palloc(NAMEDATALEN);
+		result = palloc_array(char, NAMEDATALEN);
 		snprintf(result, NAMEDATALEN, "%u", classid);
 	}
 
@@ -1138,7 +1138,7 @@ regcollationout(PG_FUNCTION_ARGS)
 	else
 	{
 		/* If OID doesn't match any pg_collation entry, return it numerically */
-		result = (char *) palloc(NAMEDATALEN);
+		result = palloc_array(char, NAMEDATALEN);
 		snprintf(result, NAMEDATALEN, "%u", collationid);
 	}
 
@@ -1289,7 +1289,7 @@ regtypeout(PG_FUNCTION_ARGS)
 	else
 	{
 		/* If OID doesn't match any pg_type entry, return it numerically */
-		result = (char *) palloc(NAMEDATALEN);
+		result = palloc_array(char, NAMEDATALEN);
 		snprintf(result, NAMEDATALEN, "%u", typid);
 	}
 
@@ -1399,7 +1399,7 @@ regconfigout(PG_FUNCTION_ARGS)
 	else
 	{
 		/* If OID doesn't match any pg_ts_config row, return it numerically */
-		result = (char *) palloc(NAMEDATALEN);
+		result = palloc_array(char, NAMEDATALEN);
 		snprintf(result, NAMEDATALEN, "%u", cfgid);
 	}
 
@@ -1510,7 +1510,7 @@ regdictionaryout(PG_FUNCTION_ARGS)
 	else
 	{
 		/* If OID doesn't match any pg_ts_dict row, return it numerically */
-		result = (char *) palloc(NAMEDATALEN);
+		result = palloc_array(char, NAMEDATALEN);
 		snprintf(result, NAMEDATALEN, "%u", dictid);
 	}
 
@@ -1627,7 +1627,7 @@ regroleout(PG_FUNCTION_ARGS)
 	else
 	{
 		/* If OID doesn't match any role, return it numerically */
-		result = (char *) palloc(NAMEDATALEN);
+		result = palloc_array(char, NAMEDATALEN);
 		snprintf(result, NAMEDATALEN, "%u", roleoid);
 	}
 
@@ -1744,7 +1744,7 @@ regnamespaceout(PG_FUNCTION_ARGS)
 	else
 	{
 		/* If OID doesn't match any namespace, return it numerically */
-		result = (char *) palloc(NAMEDATALEN);
+		result = palloc_array(char, NAMEDATALEN);
 		snprintf(result, NAMEDATALEN, "%u", nspid);
 	}
 
@@ -1861,7 +1861,7 @@ regdatabaseout(PG_FUNCTION_ARGS)
 	else
 	{
 		/* If OID doesn't match any database, return it numerically */
-		result = (char *) palloc(NAMEDATALEN);
+		result = palloc_array(char, NAMEDATALEN);
 		snprintf(result, NAMEDATALEN, "%u", dboid);
 	}
 
diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c
index d6126d431d9..d94989ad116 100644
--- a/src/backend/utils/adt/rowtypes.c
+++ b/src/backend/utils/adt/rowtypes.c
@@ -901,11 +901,11 @@ record_cmp(FunctionCallInfo fcinfo)
 	}
 
 	/* Break down the tuples into fields */
-	values1 = (Datum *) palloc(ncolumns1 * sizeof(Datum));
-	nulls1 = (bool *) palloc(ncolumns1 * sizeof(bool));
+	values1 = palloc_array(Datum, ncolumns1);
+	nulls1 = palloc_array(bool, ncolumns1);
 	heap_deform_tuple(&tuple1, tupdesc1, values1, nulls1);
-	values2 = (Datum *) palloc(ncolumns2 * sizeof(Datum));
-	nulls2 = (bool *) palloc(ncolumns2 * sizeof(bool));
+	values2 = palloc_array(Datum, ncolumns2);
+	nulls2 = palloc_array(bool, ncolumns2);
 	heap_deform_tuple(&tuple2, tupdesc2, values2, nulls2);
 
 	/*
@@ -1145,11 +1145,11 @@ record_eq(PG_FUNCTION_ARGS)
 	}
 
 	/* Break down the tuples into fields */
-	values1 = (Datum *) palloc(ncolumns1 * sizeof(Datum));
-	nulls1 = (bool *) palloc(ncolumns1 * sizeof(bool));
+	values1 = palloc_array(Datum, ncolumns1);
+	nulls1 = palloc_array(bool, ncolumns1);
 	heap_deform_tuple(&tuple1, tupdesc1, values1, nulls1);
-	values2 = (Datum *) palloc(ncolumns2 * sizeof(Datum));
-	nulls2 = (bool *) palloc(ncolumns2 * sizeof(bool));
+	values2 = palloc_array(Datum, ncolumns2);
+	nulls2 = palloc_array(bool, ncolumns2);
 	heap_deform_tuple(&tuple2, tupdesc2, values2, nulls2);
 
 	/*
@@ -1425,11 +1425,11 @@ record_image_cmp(FunctionCallInfo fcinfo)
 	}
 
 	/* Break down the tuples into fields */
-	values1 = (Datum *) palloc(ncolumns1 * sizeof(Datum));
-	nulls1 = (bool *) palloc(ncolumns1 * sizeof(bool));
+	values1 = palloc_array(Datum, ncolumns1);
+	nulls1 = palloc_array(bool, ncolumns1);
 	heap_deform_tuple(&tuple1, tupdesc1, values1, nulls1);
-	values2 = (Datum *) palloc(ncolumns2 * sizeof(Datum));
-	nulls2 = (bool *) palloc(ncolumns2 * sizeof(bool));
+	values2 = palloc_array(Datum, ncolumns2);
+	nulls2 = palloc_array(bool, ncolumns2);
 	heap_deform_tuple(&tuple2, tupdesc2, values2, nulls2);
 
 	/*
@@ -1671,11 +1671,11 @@ record_image_eq(PG_FUNCTION_ARGS)
 	}
 
 	/* Break down the tuples into fields */
-	values1 = (Datum *) palloc(ncolumns1 * sizeof(Datum));
-	nulls1 = (bool *) palloc(ncolumns1 * sizeof(bool));
+	values1 = palloc_array(Datum, ncolumns1);
+	nulls1 = palloc_array(bool, ncolumns1);
 	heap_deform_tuple(&tuple1, tupdesc1, values1, nulls1);
-	values2 = (Datum *) palloc(ncolumns2 * sizeof(Datum));
-	nulls2 = (bool *) palloc(ncolumns2 * sizeof(bool));
+	values2 = palloc_array(Datum, ncolumns2);
+	nulls2 = palloc_array(bool, ncolumns2);
 	heap_deform_tuple(&tuple2, tupdesc2, values2, nulls2);
 
 	/*
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 1d41c06201b..759ea6b06c1 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -2931,7 +2931,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
 				deconstruct_array_builtin(DatumGetArrayTypeP(val), OIDOID,
 										  &elems, NULL, &nElems);
 
-				operators = (Oid *) palloc(nElems * sizeof(Oid));
+				operators = palloc_array(Oid, nElems);
 				for (i = 0; i < nElems; i++)
 					operators[i] = DatumGetObjectId(elems[i]);
 
@@ -4132,8 +4132,7 @@ deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
 		int			ntables = list_length(dpns->rtable);
 		ListCell   *lc;
 
-		dpns->appendrels = (AppendRelInfo **)
-			palloc0((ntables + 1) * sizeof(AppendRelInfo *));
+		dpns->appendrels = palloc0_array(AppendRelInfo *, ntables + 1);
 		foreach(lc, pstmt->appendRelations)
 		{
 			AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
@@ -4346,7 +4345,7 @@ set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
 			{
 				/* Name already in use, must choose a new one */
 				int			refnamelen = strlen(refname);
-				char	   *modname = (char *) palloc(refnamelen + 16);
+				char	   *modname = palloc_array(char, refnamelen + 16);
 				NameHashEntry *hentry2;
 
 				do
@@ -4762,7 +4761,7 @@ set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
 		tupdesc = RelationGetDescr(rel);
 
 		ncolumns = tupdesc->natts;
-		real_colnames = (char **) palloc(ncolumns * sizeof(char *));
+		real_colnames = palloc_array(char *, ncolumns);
 
 		for (i = 0; i < ncolumns; i++)
 		{
@@ -4806,7 +4805,7 @@ set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
 			colnames = rte->eref->colnames;
 
 		ncolumns = list_length(colnames);
-		real_colnames = (char **) palloc(ncolumns * sizeof(char *));
+		real_colnames = palloc_array(char *, ncolumns);
 
 		i = 0;
 		foreach(lc, colnames)
@@ -4842,8 +4841,8 @@ set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
 	 * colname_is_unique will not consult that array, which is fine because it
 	 * would only be duplicate effort.
 	 */
-	colinfo->new_colnames = (char **) palloc(ncolumns * sizeof(char *));
-	colinfo->is_new_col = (bool *) palloc(ncolumns * sizeof(bool));
+	colinfo->new_colnames = palloc_array(char *, ncolumns);
+	colinfo->is_new_col = palloc_array(bool, ncolumns);
 
 	/* If the RTE is wide enough, use a hash table to avoid O(N^2) costs */
 	build_colinfo_names_hash(colinfo);
@@ -5045,8 +5044,8 @@ set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
 	nnewcolumns = leftcolinfo->num_new_cols + rightcolinfo->num_new_cols -
 		list_length(colinfo->usingNames);
 	colinfo->num_new_cols = nnewcolumns;
-	colinfo->new_colnames = (char **) palloc0(nnewcolumns * sizeof(char *));
-	colinfo->is_new_col = (bool *) palloc0(nnewcolumns * sizeof(bool));
+	colinfo->new_colnames = palloc0_array(char *, nnewcolumns);
+	colinfo->is_new_col = palloc0_array(bool, nnewcolumns);
 
 	/*
 	 * Generating the new_colnames array is a bit tricky since any new columns
@@ -5296,7 +5295,7 @@ make_colname_unique(char *colname, deparse_namespace *dpns,
 	if (!colname_is_unique(colname, dpns, colinfo))
 	{
 		int			colnamelen = strlen(colname);
-		char	   *modname = (char *) palloc(colnamelen + 16);
+		char	   *modname = palloc_array(char, colnamelen + 16);
 		int			i = 0;
 
 		do
@@ -5458,8 +5457,8 @@ identify_join_columns(JoinExpr *j, RangeTblEntry *jrte,
 	/* Initialize result arrays with zeroes */
 	numjoincols = list_length(jrte->joinaliasvars);
 	Assert(numjoincols == list_length(jrte->eref->colnames));
-	colinfo->leftattnos = (int *) palloc0(numjoincols * sizeof(int));
-	colinfo->rightattnos = (int *) palloc0(numjoincols * sizeof(int));
+	colinfo->leftattnos = palloc0_array(int, numjoincols);
+	colinfo->rightattnos = palloc0_array(int, numjoincols);
 
 	/*
 	 * Deconstruct RTE's joinleftcols/joinrightcols into desired format.
@@ -8826,7 +8825,7 @@ get_name_for_var_field(Var *var, int fieldno,
 
 					if (!dpns->inner_plan)
 					{
-						char	   *dummy_name = palloc(32);
+						char	   *dummy_name = palloc_array(char, 32);
 
 						Assert(dpns->plan && IsA(dpns->plan, Result));
 						snprintf(dummy_name, 32, "f%d", fieldno);
@@ -8957,7 +8956,7 @@ get_name_for_var_field(Var *var, int fieldno,
 
 					if (!dpns->inner_plan)
 					{
-						char	   *dummy_name = palloc(32);
+						char	   *dummy_name = palloc_array(char, 32);
 
 						Assert(dpns->plan && IsA(dpns->plan, Result));
 						snprintf(dummy_name, 32, "f%d", fieldno);
@@ -13881,7 +13880,7 @@ quote_identifier(const char *ident)
 	if (safe)
 		return ident;			/* no change needed */
 
-	result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
+	result = palloc_array(char, strlen(ident) + nquotes + 2 + 1);
 
 	optr = result;
 	*optr++ = '"';
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 2b4e6acf9a7..26731abb6b8 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -2470,8 +2470,8 @@ eqjoinsel(PG_FUNCTION_ARGS)
 	if (have_mcvs1 && have_mcvs2)
 	{
 		fmgr_info(opfuncoid, &eqproc);
-		hasmatch1 = (bool *) palloc0(sslot1.nvalues * sizeof(bool));
-		hasmatch2 = (bool *) palloc0(sslot2.nvalues * sizeof(bool));
+		hasmatch1 = palloc0_array(bool, sslot1.nvalues);
+		hasmatch2 = palloc0_array(bool, sslot2.nvalues);
 
 		/*
 		 * If the MCV lists are long enough to justify hashing, try to look up
@@ -5274,7 +5274,7 @@ convert_string_datum(Datum value, Oid typid, Oid collid, bool *failure)
 	switch (typid)
 	{
 		case CHAROID:
-			val = (char *) palloc(2);
+			val = palloc_array(char, 2);
 			val[0] = DatumGetChar(value);
 			val[1] = '\0';
 			break;
@@ -5335,7 +5335,7 @@ convert_string_datum(Datum value, Oid typid, Oid collid, bool *failure)
 		if (xfrmlen == INT_MAX)
 			return val;
 #endif
-		xfrmstr = (char *) palloc(xfrmlen + 1);
+		xfrmstr = palloc_array(char, xfrmlen + 1);
 		xfrmlen2 = pg_strxfrm(xfrmstr, val, xfrmlen + 1, mylocale);
 
 		/*
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index a20e7ea1d11..9a3b7005268 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -1127,7 +1127,7 @@ Datum
 intervaltypmodout(PG_FUNCTION_ARGS)
 {
 	int32		typmod = PG_GETARG_INT32(0);
-	char	   *res = (char *) palloc(64);
+	char	   *res = palloc_array(char, 64);
 	int			fields;
 	int			precision;
 	const char *fieldstr;
diff --git a/src/backend/utils/adt/tsquery.c b/src/backend/utils/adt/tsquery.c
index e411a21f07e..c9797f632d1 100644
--- a/src/backend/utils/adt/tsquery.c
+++ b/src/backend/utils/adt/tsquery.c
@@ -861,7 +861,7 @@ parse_tsquery(char *buf,
 	/* init list of operand */
 	state.sumlen = 0;
 	state.lenop = 64;
-	state.curop = state.op = (char *) palloc(state.lenop);
+	state.curop = state.op = palloc_array(char, state.lenop);
 	*(state.curop) = '\0';
 
 	/* parse query & make polish notation (postfix, but in reverse order) */
@@ -1240,7 +1240,7 @@ tsqueryrecv(PG_FUNCTION_ARGS)
 		elog(ERROR, "invalid size of tsquery");
 
 	/* Allocate space to temporarily hold operand strings */
-	operands = palloc(size * sizeof(char *));
+	operands = palloc_array(const char *, size);
 
 	/* Allocate space for all the QueryItems. */
 	len = HDRSIZETQ + sizeof(QueryItem) * size;
diff --git a/src/backend/utils/adt/tsquery_cleanup.c b/src/backend/utils/adt/tsquery_cleanup.c
index 1dc9240970e..79c3e6ef1d0 100644
--- a/src/backend/utils/adt/tsquery_cleanup.c
+++ b/src/backend/utils/adt/tsquery_cleanup.c
@@ -102,7 +102,7 @@ plaintree(NODE *root, int *len)
 	pl.len = 16;
 	if (root && (root->valnode->type == QI_VAL || root->valnode->type == QI_OPR))
 	{
-		pl.ptr = (QueryItem *) palloc(pl.len * sizeof(QueryItem));
+		pl.ptr = palloc_array(QueryItem, pl.len);
 		plainnode(&pl, root);
 	}
 	else
diff --git a/src/backend/utils/adt/tsquery_rewrite.c b/src/backend/utils/adt/tsquery_rewrite.c
index aace2a4c7d6..ecff1035c3e 100644
--- a/src/backend/utils/adt/tsquery_rewrite.c
+++ b/src/backend/utils/adt/tsquery_rewrite.c
@@ -92,7 +92,7 @@ findeq(QTNode *node, QTNode *ex, QTNode *subs, bool *isfind)
 				   node->valnode->qoperator.oper == OP_OR);
 
 			/* matched[] will record which children of node matched */
-			matched = (bool *) palloc0(node->nchild * sizeof(bool));
+			matched = palloc0_array(bool, node->nchild);
 			nmatched = 0;
 			i = j = 0;
 			while (i < node->nchild && j < ex->nchild)
diff --git a/src/backend/utils/adt/tsvector.c b/src/backend/utils/adt/tsvector.c
index 024f5160cd4..84e2a70297f 100644
--- a/src/backend/utils/adt/tsvector.c
+++ b/src/backend/utils/adt/tsvector.c
@@ -331,7 +331,7 @@ tsvectorout(PG_FUNCTION_ARGS)
 			lenbuf += 1 /* : */ + 7 /* int2 + , + weight */ * POSDATALEN(out, &(ptr[i]));
 	}
 
-	curout = outbuf = (char *) palloc(lenbuf);
+	curout = outbuf = palloc_array(char, lenbuf);
 	for (i = 0; i < out->size; i++)
 	{
 		curin = STRPTR(out) + ptr->pos;
diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c
index ea62efebdce..6214942a103 100644
--- a/src/backend/utils/adt/tsvector_op.c
+++ b/src/backend/utils/adt/tsvector_op.c
@@ -589,7 +589,7 @@ tsvector_delete_arr(PG_FUNCTION_ARGS)
 	 * here we optimize things for that scenario: iterate through lexarr
 	 * performing binary search of each lexeme from lexarr in tsvector.
 	 */
-	skip_indices = palloc0(nlex * sizeof(int));
+	skip_indices = palloc0_array(int, nlex);
 	for (i = skip_count = 0; i < nlex; i++)
 	{
 		char	   *lex;
@@ -682,8 +682,8 @@ tsvector_unnest(PG_FUNCTION_ARGS)
 			 * that in two separate arrays.
 			 */
 			posv = _POSVECPTR(tsin, arrin + i);
-			positions = palloc(posv->npos * sizeof(Datum));
-			weights = palloc(posv->npos * sizeof(Datum));
+			positions = palloc_array(Datum, posv->npos);
+			weights = palloc_array(Datum, posv->npos);
 			for (j = 0; j < posv->npos; j++)
 			{
 				positions[j] = Int16GetDatum(WEP_GETPOS(posv->pos[j]));
@@ -721,7 +721,7 @@ tsvector_to_array(PG_FUNCTION_ARGS)
 	int			i;
 	ArrayType  *array;
 
-	elements = palloc(tsin->size * sizeof(Datum));
+	elements = palloc_array(Datum, tsin->size);
 
 	for (i = 0; i < tsin->size; i++)
 	{
@@ -1512,8 +1512,7 @@ TS_phrase_output(ExecPhraseData *data,
 				/* Store position, first allocating output array if needed */
 				if (data->pos == NULL)
 				{
-					data->pos = (WordEntryPos *)
-						palloc(max_npos * sizeof(WordEntryPos));
+					data->pos = palloc_array(WordEntryPos, max_npos);
 					data->allocated = true;
 				}
 				data->pos[data->npos++] = output_pos;
diff --git a/src/backend/utils/adt/tsvector_parser.c b/src/backend/utils/adt/tsvector_parser.c
index efeaeb55334..d7d12236b0e 100644
--- a/src/backend/utils/adt/tsvector_parser.c
+++ b/src/backend/utils/adt/tsvector_parser.c
@@ -62,7 +62,7 @@ init_tsvector_parser(char *input, int flags, Node *escontext)
 	state->prsbuf = input;
 	state->bufstart = input;
 	state->len = 32;
-	state->word = (char *) palloc(state->len);
+	state->word = palloc_array(char, state->len);
 	state->eml = pg_database_encoding_max_length();
 	state->oprisdelim = (flags & P_TSV_OPR_IS_DELIM) != 0;
 	state->is_tsquery = (flags & P_TSV_IS_TSQUERY) != 0;
diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c
index fe49ba851ac..ade00cde3b1 100644
--- a/src/backend/utils/adt/varbit.c
+++ b/src/backend/utils/adt/varbit.c
@@ -126,7 +126,7 @@ anybit_typmodin(ArrayType *ta, const char *typename)
 static char *
 anybit_typmodout(int32 typmod)
 {
-	char	   *res = (char *) palloc(64);
+	char	   *res = palloc_array(char, 64);
 
 	if (typmod >= 0)
 		snprintf(res, 64, "(%d)", typmod);
@@ -301,7 +301,7 @@ bit_out(PG_FUNCTION_ARGS)
 
 	bitlen = VARBITLEN(s);
 	len = (bitlen + 3) / 4;
-	result = (char *) palloc(len + 2);
+	result = palloc_array(char, len + 2);
 	sp = VARBITS(s);
 	r = result;
 	*r++ = 'X';
@@ -599,7 +599,7 @@ varbit_out(PG_FUNCTION_ARGS)
 	VARBIT_CORRECTLY_PADDED(s);
 
 	len = VARBITLEN(s);
-	result = (char *) palloc(len + 1);
+	result = palloc_array(char, len + 1);
 	sp = VARBITS(s);
 	r = result;
 	for (i = 0; i <= len - BITS_PER_BYTE; i += BITS_PER_BYTE, sp++)
diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c
index 45b7ef185a1..62e28b07933 100644
--- a/src/backend/utils/adt/varchar.c
+++ b/src/backend/utils/adt/varchar.c
@@ -71,7 +71,7 @@ anychar_typmodin(ArrayType *ta, const char *typename)
 static char *
 anychar_typmodout(int32 typmod)
 {
-	char	   *res = (char *) palloc(64);
+	char	   *res = palloc_array(char, 64);
 
 	if (typmod > VARHDRSZ)
 		snprintf(res, 64, "(%d)", (int) (typmod - VARHDRSZ));
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 0c6d3ba4d22..305ecd3f59c 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -221,7 +221,7 @@ text_to_cstring(const text *t)
 	int			len = VARSIZE_ANY_EXHDR(tunpacked);
 	char	   *result;
 
-	result = (char *) palloc(len + 1);
+	result = palloc_array(char, len + 1);
 	memcpy(result, VARDATA_ANY(tunpacked), len);
 	result[len] = '\0';
 
@@ -1750,9 +1750,9 @@ varstr_sortsupport(SortSupport ssup, Oid typid, Oid collid)
 	if (abbreviate || !collate_c)
 	{
 		sss = palloc_object(VarStringSortSupport);
-		sss->buf1 = palloc(TEXTBUFLEN);
+		sss->buf1 = palloc_array(char, TEXTBUFLEN);
 		sss->buflen1 = TEXTBUFLEN;
-		sss->buf2 = palloc(TEXTBUFLEN);
+		sss->buf2 = palloc_array(char, TEXTBUFLEN);
 		sss->buflen2 = TEXTBUFLEN;
 		/* Start with invalid values */
 		sss->last_len1 = -1;
@@ -3365,7 +3365,7 @@ replace_text_regexp(text *src_text, text *pattern_text,
 	initStringInfo(&buf);
 
 	/* Convert data string to wide characters. */
-	data = (pg_wchar *) palloc((src_text_len + 1) * sizeof(pg_wchar));
+	data = palloc_array(pg_wchar, src_text_len + 1);
 	data_len = pg_mb2wchar_with_len(VARDATA_ANY(src_text), data, src_text_len);
 
 	/* Check whether replace_text has escapes, especially regexp submatches. */
diff --git a/src/backend/utils/adt/xid.c b/src/backend/utils/adt/xid.c
index f746a5f97dd..f078fb8e9ef 100644
--- a/src/backend/utils/adt/xid.c
+++ b/src/backend/utils/adt/xid.c
@@ -43,7 +43,7 @@ Datum
 xidout(PG_FUNCTION_ARGS)
 {
 	TransactionId transactionId = PG_GETARG_TRANSACTIONID(0);
-	char	   *result = (char *) palloc(16);
+	char	   *result = palloc_array(char, 16);
 
 	snprintf(result, 16, "%u", transactionId);
 	PG_RETURN_CSTRING(result);
@@ -205,7 +205,7 @@ Datum
 xid8out(PG_FUNCTION_ARGS)
 {
 	FullTransactionId fxid = PG_GETARG_FULLTRANSACTIONID(0);
-	char	   *result = (char *) palloc(21);
+	char	   *result = palloc_array(char, 21);
 
 	snprintf(result, 21, UINT64_FORMAT, U64FromFullTransactionId(fxid));
 	PG_RETURN_CSTRING(result);
@@ -360,7 +360,7 @@ Datum
 cidout(PG_FUNCTION_ARGS)
 {
 	CommandId	c = PG_GETARG_COMMANDID(0);
-	char	   *result = (char *) palloc(16);
+	char	   *result = palloc_array(char, 16);
 
 	snprintf(result, 16, "%u", c);
 	PG_RETURN_CSTRING(result);
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 0953ad2becb..1f75ffcfd9d 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -1419,7 +1419,7 @@ xml_pnstrdup(const xmlChar *str, size_t len)
 {
 	xmlChar    *result;
 
-	result = (xmlChar *) palloc((len + 1) * sizeof(xmlChar));
+	result = palloc_array(xmlChar, len + 1);
 	memcpy(result, str, len * sizeof(xmlChar));
 	result[len] = 0;
 	return result;
@@ -1431,7 +1431,7 @@ pg_xmlCharStrndup(const char *str, size_t len)
 {
 	xmlChar    *result;
 
-	result = (xmlChar *) palloc((len + 1) * sizeof(xmlChar));
+	result = palloc_array(xmlChar, len + 1);
 	memcpy(result, str, len);
 	result[len] = '\0';
 
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 0c8955fc61a..511270edfda 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -947,7 +947,7 @@ InitCatCache(int id,
 	 */
 	cp = (CatCache *) palloc_aligned(sizeof(CatCache), PG_CACHE_LINE_SIZE,
 									 MCXT_ALLOC_ZERO);
-	cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));
+	cp->cc_bucket = palloc0_array(dlist_head, nbuckets);
 
 	/*
 	 * Many catcaches never receive any list searches.  Therefore, we don't
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c
index 63dc36d4d91..b41692dc7d1 100644
--- a/src/backend/utils/cache/inval.c
+++ b/src/backend/utils/cache/inval.c
@@ -1102,8 +1102,7 @@ inplaceGetInvalidationMessages(SharedInvalidationMessage **msgs,
 
 	*RelcacheInitFileInval = inplaceInvalInfo->RelcacheInitFileInval;
 	nummsgs = NumMessagesInGroup(&inplaceInvalInfo->CurrentCmdInvalidMsgs);
-	*msgs = msgarray = (SharedInvalidationMessage *)
-		palloc(nummsgs * sizeof(SharedInvalidationMessage));
+	*msgs = msgarray = palloc_array(SharedInvalidationMessage, nummsgs);
 
 	nmsgs = 0;
 	ProcessMessageSubGroupMulti(&inplaceInvalInfo->CurrentCmdInvalidMsgs,
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index cc6f05a0aa7..9ef3922d17c 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -2022,7 +2022,7 @@ get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
 	result = procstruct->prorettype;
 	*nargs = (int) procstruct->pronargs;
 	Assert(*nargs == procstruct->proargtypes.dim1);
-	*argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
+	*argtypes = palloc_array(Oid, *nargs);
 	memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
 
 	ReleaseSysCache(tp);
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 19c4ff6e75e..c34ca4feee5 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -3113,7 +3113,7 @@ RememberToFreeTupleDescAtEOX(TupleDesc td)
 
 		oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
-		EOXactTupleDescArray = (TupleDesc *) palloc(16 * sizeof(TupleDesc));
+		EOXactTupleDescArray = palloc_array(TupleDesc, 16);
 		EOXactTupleDescArrayLen = 16;
 		NextEOXactTupleDescNum = 0;
 		MemoryContextSwitchTo(oldcxt);
@@ -3175,7 +3175,7 @@ AssertPendingSyncs_RelationCache(void)
 	 */
 	PushActiveSnapshot(GetTransactionSnapshot());
 	maxrels = 1;
-	rels = palloc(maxrels * sizeof(*rels));
+	rels = palloc_array(Relation, maxrels);
 	nrels = 0;
 	hash_seq_init(&status, GetLockMethodLocalHash());
 	while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
@@ -6229,7 +6229,7 @@ load_relcache_init_file(bool shared)
 	 * helps to guard against broken init files.
 	 */
 	max_rels = 100;
-	rels = (Relation *) palloc(max_rels * sizeof(Relation));
+	rels = palloc_array(Relation, max_rels);
 	num_rels = 0;
 	nailed_rels = nailed_indexes = 0;
 
diff --git a/src/backend/utils/error/jsonlog.c b/src/backend/utils/error/jsonlog.c
index 4a76072830d..ba07c05a15e 100644
--- a/src/backend/utils/error/jsonlog.c
+++ b/src/backend/utils/error/jsonlog.c
@@ -80,7 +80,7 @@ appendJSONKeyValueFmt(StringInfo buf, const char *key,
 		size_t		newlen;
 
 		/* Allocate result buffer */
-		value = (char *) palloc(len);
+		value = palloc_array(char, len);
 
 		/* Try to format the data. */
 		errno = save_errno;
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index 6f0785067b8..092f0b0ff93 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -1413,7 +1413,7 @@ get_func_arg_info(HeapTuple procTup,
 			ARR_ELEMTYPE(arr) != OIDOID)
 			elog(ERROR, "proallargtypes is not a 1-D Oid array or it contains nulls");
 		Assert(numargs >= procStruct->pronargs);
-		*p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
+		*p_argtypes = palloc_array(Oid, numargs);
 		memcpy(*p_argtypes, ARR_DATA_PTR(arr),
 			   numargs * sizeof(Oid));
 	}
@@ -1422,7 +1422,7 @@ get_func_arg_info(HeapTuple procTup,
 		/* If no proallargtypes, use proargtypes */
 		numargs = procStruct->proargtypes.dim1;
 		Assert(numargs == procStruct->pronargs);
-		*p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
+		*p_argtypes = palloc_array(Oid, numargs);
 		memcpy(*p_argtypes, procStruct->proargtypes.values,
 			   numargs * sizeof(Oid));
 	}
@@ -1459,7 +1459,7 @@ get_func_arg_info(HeapTuple procTup,
 			ARR_ELEMTYPE(arr) != CHAROID)
 			elog(ERROR, "proargmodes is not a 1-D char array of length %d or it contains nulls",
 				 numargs);
-		*p_argmodes = (char *) palloc(numargs * sizeof(char));
+		*p_argmodes = palloc_array(char, numargs);
 		memcpy(*p_argmodes, ARR_DATA_PTR(arr),
 			   numargs * sizeof(char));
 	}
@@ -1501,7 +1501,7 @@ get_func_trftypes(HeapTuple procTup,
 			ARR_HASNULL(arr) ||
 			ARR_ELEMTYPE(arr) != OIDOID)
 			elog(ERROR, "protrftypes is not a 1-D Oid array or it contains nulls");
-		*p_trftypes = (Oid *) palloc(nelems * sizeof(Oid));
+		*p_trftypes = palloc_array(Oid, nelems);
 		memcpy(*p_trftypes, ARR_DATA_PTR(arr),
 			   nelems * sizeof(Oid));
 
@@ -1573,7 +1573,7 @@ get_func_input_arg_names(Datum proargnames, Datum proargmodes,
 	}
 
 	/* extract input-argument names */
-	inargnames = (char **) palloc(numargs * sizeof(char *));
+	inargnames = palloc_array(char *, numargs);
 	numinargs = 0;
 	for (i = 0; i < numargs; i++)
 	{
@@ -1812,8 +1812,8 @@ build_function_result_tupdesc_d(char prokind,
 		return NULL;
 
 	/* extract output-argument types and names */
-	outargtypes = (Oid *) palloc(numargs * sizeof(Oid));
-	outargnames = (char **) palloc(numargs * sizeof(char *));
+	outargtypes = palloc_array(Oid, numargs);
+	outargnames = palloc_array(char *, numargs);
 	numoutargs = 0;
 	for (i = 0; i < numargs; i++)
 	{
@@ -2046,7 +2046,7 @@ extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start,
 						  &nargs);
 
 		/* All the elements of the array have the same type */
-		types_res = (Oid *) palloc0(nargs * sizeof(Oid));
+		types_res = palloc0_array(Oid, nargs);
 		for (i = 0; i < nargs; i++)
 			types_res[i] = element_type;
 	}
@@ -2054,9 +2054,9 @@ extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start,
 	{
 		nargs = PG_NARGS() - variadic_start;
 		Assert(nargs > 0);
-		nulls_res = (bool *) palloc0(nargs * sizeof(bool));
-		args_res = (Datum *) palloc0(nargs * sizeof(Datum));
-		types_res = (Oid *) palloc0(nargs * sizeof(Oid));
+		nulls_res = palloc0_array(bool, nargs);
+		args_res = palloc0_array(Datum, nargs);
+		types_res = palloc0_array(Oid, nargs);
 
 		for (i = 0; i < nargs; i++)
 		{
diff --git a/src/backend/utils/sort/logtape.c b/src/backend/utils/sort/logtape.c
index ebe2861cf57..2e8fab35e7b 100644
--- a/src/backend/utils/sort/logtape.c
+++ b/src/backend/utils/sort/logtape.c
@@ -566,7 +566,7 @@ LogicalTapeSetCreate(bool preallocate, SharedFileSet *fileset, int worker)
 	lts->nHoleBlocks = 0L;
 	lts->forgetFreeSpace = false;
 	lts->freeBlocksLen = 32;	/* reasonable initial guess */
-	lts->freeBlocks = (int64 *) palloc(lts->freeBlocksLen * sizeof(int64));
+	lts->freeBlocks = palloc_array(int64, lts->freeBlocksLen);
 	lts->nFreeBlocks = 0;
 	lts->enable_prealloc = preallocate;
 
@@ -769,7 +769,7 @@ LogicalTapeWrite(LogicalTape *lt, const void *ptr, size_t size)
 	/* Allocate data buffer and first block on first write */
 	if (lt->buffer == NULL)
 	{
-		lt->buffer = (char *) palloc(BLCKSZ);
+		lt->buffer = palloc_array(char, BLCKSZ);
 		lt->buffer_size = BLCKSZ;
 	}
 	if (lt->curBlockNumber == -1)
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index c0e7527b9ca..ab783b43767 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -699,7 +699,7 @@ tuplesort_begin_batch(Tuplesortstate *state)
 	}
 	if (state->memtuples == NULL)
 	{
-		state->memtuples = (SortTuple *) palloc(state->memtupsize * sizeof(SortTuple));
+		state->memtuples = palloc_array(SortTuple, state->memtupsize);
 		USEMEM(state, GetMemoryChunkSpace(state->memtuples));
 	}
 
@@ -1795,7 +1795,7 @@ inittapes(Tuplesortstate *state, bool mergeruns)
 	state->nInputTapes = 0;
 	state->nInputRuns = 0;
 
-	state->outputTapes = palloc0(state->maxTapes * sizeof(LogicalTape *));
+	state->outputTapes = palloc0_array(LogicalTape *, state->maxTapes);
 	state->nOutputTapes = 0;
 	state->nOutputRuns = 0;
 
@@ -2020,7 +2020,7 @@ mergeruns(Tuplesortstate *state)
 			 * created as needed, here we only allocate the array to hold
 			 * them.
 			 */
-			state->outputTapes = palloc0(state->nInputTapes * sizeof(LogicalTape *));
+			state->outputTapes = palloc0_array(LogicalTape *, state->nInputTapes);
 			state->nOutputTapes = 0;
 			state->nOutputRuns = 0;
 
@@ -3420,7 +3420,7 @@ leader_takeover_tapes(Tuplesortstate *state)
 	state->nInputTapes = 0;
 	state->nInputRuns = 0;
 
-	state->outputTapes = palloc0(nParticipants * sizeof(LogicalTape *));
+	state->outputTapes = palloc0_array(LogicalTape *, nParticipants);
 	state->nOutputTapes = nParticipants;
 	state->nOutputRuns = nParticipants;
 
diff --git a/src/backend/utils/sort/tuplesortvariants.c b/src/backend/utils/sort/tuplesortvariants.c
index 2509ac3e3a4..95b9ff9d39a 100644
--- a/src/backend/utils/sort/tuplesortvariants.c
+++ b/src/backend/utils/sort/tuplesortvariants.c
@@ -217,7 +217,7 @@ tuplesort_begin_heap(TupleDesc tupDesc,
 	base->arg = tupDesc;		/* assume we need not copy tupDesc */
 
 	/* Prepare SortSupport data for each column */
-	base->sortKeys = (SortSupport) palloc0(nkeys * sizeof(SortSupportData));
+	base->sortKeys = (SortSupport) palloc0_array(SortSupportData, nkeys);
 
 	for (i = 0; i < nkeys; i++)
 	{
@@ -325,8 +325,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
 	}
 
 	/* Prepare SortSupport data for each column */
-	base->sortKeys = (SortSupport) palloc0(base->nKeys *
-										   sizeof(SortSupportData));
+	base->sortKeys = (SortSupport) palloc0_array(SortSupportData, base->nKeys);
 
 	for (i = 0; i < base->nKeys; i++)
 	{
@@ -407,8 +406,7 @@ tuplesort_begin_index_btree(Relation heapRel,
 	indexScanKey = _bt_mkscankey(indexRel, NULL);
 
 	/* Prepare SortSupport data for each column */
-	base->sortKeys = (SortSupport) palloc0(base->nKeys *
-										   sizeof(SortSupportData));
+	base->sortKeys = (SortSupport) palloc0_array(SortSupportData, base->nKeys);
 
 	for (i = 0; i < base->nKeys; i++)
 	{
@@ -527,8 +525,7 @@ tuplesort_begin_index_gist(Relation heapRel,
 	arg->uniqueNullsNotDistinct = false;
 
 	/* Prepare SortSupport data for each column */
-	base->sortKeys = (SortSupport) palloc0(base->nKeys *
-										   sizeof(SortSupportData));
+	base->sortKeys = (SortSupport) palloc0_array(SortSupportData, base->nKeys);
 
 	for (i = 0; i < base->nKeys; i++)
 	{
@@ -610,8 +607,7 @@ tuplesort_begin_index_gin(Relation heapRel,
 	base->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
 
 	/* Prepare SortSupport data for each column */
-	base->sortKeys = (SortSupport) palloc0(base->nKeys *
-										   sizeof(SortSupportData));
+	base->sortKeys = (SortSupport) palloc0_array(SortSupportData, base->nKeys);
 
 	for (i = 0; i < base->nKeys; i++)
 	{
diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c
index f9e2d95186a..fc8adeef18c 100644
--- a/src/backend/utils/sort/tuplestore.c
+++ b/src/backend/utils/sort/tuplestore.c
@@ -291,15 +291,14 @@ tuplestore_begin_common(int eflags, bool interXact, int maxKBytes)
 							ALLOCSET_SEPARATE_THRESHOLD / sizeof(void *) + 1);
 
 	state->growmemtuples = true;
-	state->memtuples = (void **) palloc(state->memtupsize * sizeof(void *));
+	state->memtuples = palloc_array(void *, state->memtupsize);
 
 	USEMEM(state, GetMemoryChunkSpace(state->memtuples));
 
 	state->activeptr = 0;
 	state->readptrcount = 1;
 	state->readptrsize = 8;		/* arbitrary */
-	state->readptrs = (TSReadPointer *)
-		palloc(state->readptrsize * sizeof(TSReadPointer));
+	state->readptrs = palloc_array(TSReadPointer, state->readptrsize);
 
 	state->readptrs[0].eflags = eflags;
 	state->readptrs[0].eof_reached = false;
diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index bc98a4361bf..c1b02d63652 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -1455,7 +1455,7 @@ ImportSnapshot(const char *idstr)
 		elog(ERROR, "could not stat file \"%s\": %m", path);
 
 	/* and read the file into a palloc'd string */
-	filebuf = (char *) palloc(stat_buf.st_size + 1);
+	filebuf = palloc_array(char, stat_buf.st_size + 1);
 	if (fread(filebuf, stat_buf.st_size, 1, f) != 1)
 		elog(ERROR, "could not read file \"%s\": %m", path);
 
@@ -1488,7 +1488,7 @@ ImportSnapshot(const char *idstr)
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid snapshot data in file \"%s\"", path)));
 
-	snapshot.xip = (TransactionId *) palloc(xcnt * sizeof(TransactionId));
+	snapshot.xip = palloc_array(TransactionId, xcnt);
 	for (i = 0; i < xcnt; i++)
 		snapshot.xip[i] = parseXidFromText("xip:", &filebuf, path);
 
@@ -1504,7 +1504,7 @@ ImportSnapshot(const char *idstr)
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid snapshot data in file \"%s\"", path)));
 
-		snapshot.subxip = (TransactionId *) palloc(xcnt * sizeof(TransactionId));
+		snapshot.subxip = palloc_array(TransactionId, xcnt);
 		for (i = 0; i < xcnt; i++)
 			snapshot.subxip[i] = parseXidFromText("sxp:", &filebuf, path);
 	}
diff --git a/src/bin/scripts/vacuuming.c b/src/bin/scripts/vacuuming.c
index 855a5754c98..611b94999a9 100644
--- a/src/bin/scripts/vacuuming.c
+++ b/src/bin/scripts/vacuuming.c
@@ -459,7 +459,7 @@ vacuum_all_databases(ConnParams *cparams,
 		SimpleStringList **found_objs = NULL;
 
 		if (vacopts->missing_stats_only)
-			found_objs = palloc0(numdbs * sizeof(SimpleStringList *));
+			found_objs = palloc0_array(SimpleStringList *, numdbs);
 
 		/*
 		 * When analyzing all databases in stages, we analyze them all in the
diff --git a/src/common/blkreftable.c b/src/common/blkreftable.c
index 63e068a8f18..9e0db8a5433 100644
--- a/src/common/blkreftable.c
+++ b/src/common/blkreftable.c
@@ -1105,7 +1105,7 @@ BlockRefTableEntryMarkBlockModified(BlockRefTableEntry *entry,
 		unsigned	j;
 
 		/* Allocate a new chunk. */
-		newchunk = palloc0(MAX_ENTRIES_PER_CHUNK * sizeof(uint16));
+		newchunk = palloc0_array(uint16, MAX_ENTRIES_PER_CHUNK);
 
 		/* Set the bit for each existing entry. */
 		for (j = 0; j < entry->chunk_usage[chunkno]; ++j)
diff --git a/src/common/d2s.c b/src/common/d2s.c
index 0a9cb83fc49..e4cd19395fe 100644
--- a/src/common/d2s.c
+++ b/src/common/d2s.c
@@ -1069,7 +1069,7 @@ double_to_shortest_decimal_buf(double f, char *result)
 char *
 double_to_shortest_decimal(double f)
 {
-	char	   *const result = (char *) palloc(DOUBLE_SHORTEST_DECIMAL_LEN);
+	char	   *const result = palloc_array(char, DOUBLE_SHORTEST_DECIMAL_LEN);
 
 	double_to_shortest_decimal_buf(f, result);
 	return result;
diff --git a/src/common/f2s.c b/src/common/f2s.c
index d81a3a43d0e..981d314cb38 100644
--- a/src/common/f2s.c
+++ b/src/common/f2s.c
@@ -796,7 +796,7 @@ float_to_shortest_decimal_buf(float f, char *result)
 char *
 float_to_shortest_decimal(float f)
 {
-	char	   *const result = (char *) palloc(FLOAT_SHORTEST_DECIMAL_LEN);
+	char	   *const result = palloc_array(char, FLOAT_SHORTEST_DECIMAL_LEN);
 
 	float_to_shortest_decimal_buf(f, result);
 	return result;
diff --git a/src/common/psprintf.c b/src/common/psprintf.c
index 29b09732a5a..b402b0be89f 100644
--- a/src/common/psprintf.c
+++ b/src/common/psprintf.c
@@ -55,7 +55,7 @@ psprintf(const char *fmt, ...)
 		 * Allocate result buffer.  Note that in frontend this maps to malloc
 		 * with exit-on-error.
 		 */
-		result = (char *) palloc(len);
+		result = palloc_array(char, len);
 
 		/* Try to format the data. */
 		errno = save_errno;
diff --git a/src/common/stringinfo.c b/src/common/stringinfo.c
index 468954e484e..e2b16d5e308 100644
--- a/src/common/stringinfo.c
+++ b/src/common/stringinfo.c
@@ -42,7 +42,7 @@ initStringInfoInternal(StringInfo str, int initsize)
 {
 	Assert(initsize >= 1 && initsize <= MaxAllocSize);
 
-	str->data = (char *) palloc(initsize);
+	str->data = palloc_array(char, initsize);
 	str->maxlen = initsize;
 	resetStringInfo(str);
 }
diff --git a/src/include/lib/simplehash.h b/src/include/lib/simplehash.h
index 15af488abfb..98572f12162 100644
--- a/src/include/lib/simplehash.h
+++ b/src/include/lib/simplehash.h
@@ -1127,7 +1127,7 @@ SH_STAT(SH_TYPE * tb)
 	double		fillfactor;
 	uint32		i;
 
-	uint32	   *collisions = (uint32 *) palloc0(tb->size * sizeof(uint32));
+	uint32	   *collisions = palloc0_array(uint32, tb->size);
 	uint32		total_collisions = 0;
 	uint32		max_collisions = 0;
 	double		avg_collisions;
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 9ddb81d42b9..9b83b55ccab 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -1792,9 +1792,9 @@ plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup)
 	tupdesc = tdata->tg_relation->rd_att;
 	natts = tupdesc->natts;
 
-	modvalues = (Datum *) palloc0(natts * sizeof(Datum));
-	modnulls = (bool *) palloc0(natts * sizeof(bool));
-	modrepls = (bool *) palloc0(natts * sizeof(bool));
+	modvalues = palloc0_array(Datum, natts);
+	modnulls = palloc0_array(bool, natts);
+	modrepls = palloc0_array(bool, natts);
 
 	hv_iterinit(hvNew);
 	while ((he = hv_iternext(hvNew)))
@@ -2811,9 +2811,9 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger)
 		prodesc->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
 		prodesc->fn_tid = procTup->t_self;
 		prodesc->nargs = procStruct->pronargs;
-		prodesc->arg_out_func = (FmgrInfo *) palloc0(prodesc->nargs * sizeof(FmgrInfo));
-		prodesc->arg_is_rowtype = (bool *) palloc0(prodesc->nargs * sizeof(bool));
-		prodesc->arg_arraytype = (Oid *) palloc0(prodesc->nargs * sizeof(Oid));
+		prodesc->arg_out_func = palloc0_array(FmgrInfo, prodesc->nargs);
+		prodesc->arg_is_rowtype = palloc0_array(bool, prodesc->nargs);
+		prodesc->arg_arraytype = palloc0_array(Oid, prodesc->nargs);
 		MemoryContextSwitchTo(oldcontext);
 
 		/* Remember if function is STABLE/IMMUTABLE */
@@ -3606,9 +3606,9 @@ plperl_spi_prepare(char *query, int argc, SV **argv)
 		snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
 		qdesc->plan_cxt = plan_cxt;
 		qdesc->nargs = argc;
-		qdesc->argtypes = (Oid *) palloc(argc * sizeof(Oid));
-		qdesc->arginfuncs = (FmgrInfo *) palloc(argc * sizeof(FmgrInfo));
-		qdesc->argtypioparams = (Oid *) palloc(argc * sizeof(Oid));
+		qdesc->argtypes = palloc_array(Oid, argc);
+		qdesc->arginfuncs = palloc_array(FmgrInfo, argc);
+		qdesc->argtypioparams = palloc_array(Oid, argc);
 		MemoryContextSwitchTo(oldcontext);
 
 		/************************************************************
@@ -3779,8 +3779,8 @@ plperl_spi_exec_prepared(char *query, HV *attr, int argc, SV **argv)
 		 ************************************************************/
 		if (argc > 0)
 		{
-			nulls = (char *) palloc(argc);
-			argvalues = (Datum *) palloc(argc * sizeof(Datum));
+			nulls = palloc_array(char, argc);
+			argvalues = palloc_array(Datum, argc);
 		}
 		else
 		{
@@ -3892,8 +3892,8 @@ plperl_spi_query_prepared(char *query, int argc, SV **argv)
 		 ************************************************************/
 		if (argc > 0)
 		{
-			nulls = (char *) palloc(argc);
-			argvalues = (Datum *) palloc(argc * sizeof(Datum));
+			nulls = palloc_array(char, argc);
+			argvalues = palloc_array(Datum, argc);
 		}
 		else
 		{
diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y
index 5009e59a78f..5e14a2d7302 100644
--- a/src/pl/plpgsql/src/pl_gram.y
+++ b/src/pl/plpgsql/src/pl_gram.y
@@ -3955,7 +3955,7 @@ read_cursor_args(PLpgSQL_var *cursor, int until, YYSTYPE *yylvalp, YYLTYPE *yyll
 	 * Read the arguments, one by one.
 	 */
 	row = (PLpgSQL_row *) plpgsql_Datums[cursor->cursor_explicit_argrow];
-	argv = (char **) palloc0_array(char *, row->nfields);
+	argv = palloc0_array(char *, row->nfields);
 
 	for (argc = 0; argc < row->nfields; argc++)
 	{
diff --git a/src/pl/plpython/plpy_cursorobject.c b/src/pl/plpython/plpy_cursorobject.c
index 0725fbc19f2..054dc97db1b 100644
--- a/src/pl/plpython/plpy_cursorobject.c
+++ b/src/pl/plpython/plpy_cursorobject.c
@@ -243,8 +243,8 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
 
 		if (nargs > 0)
 		{
-			values = (Datum *) palloc(nargs * sizeof(Datum));
-			nulls = (char *) palloc(nargs * sizeof(char));
+			values = palloc_array(Datum, nargs);
+			nulls = palloc_array(char, nargs);
 		}
 		else
 		{
diff --git a/src/pl/plpython/plpy_exec.c b/src/pl/plpython/plpy_exec.c
index de7f64113d6..14e63625070 100644
--- a/src/pl/plpython/plpy_exec.c
+++ b/src/pl/plpython/plpy_exec.c
@@ -1051,9 +1051,9 @@ PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata,
 
 		tupdesc = RelationGetDescr(tdata->tg_relation);
 
-		modvalues = (Datum *) palloc0(tupdesc->natts * sizeof(Datum));
-		modnulls = (bool *) palloc0(tupdesc->natts * sizeof(bool));
-		modrepls = (bool *) palloc0(tupdesc->natts * sizeof(bool));
+		modvalues = palloc0_array(Datum, tupdesc->natts);
+		modnulls = palloc0_array(bool, tupdesc->natts);
+		modrepls = palloc0_array(bool, tupdesc->natts);
 
 		for (i = 0; i < nkeys; i++)
 		{
diff --git a/src/pl/plpython/plpy_procedure.c b/src/pl/plpython/plpy_procedure.c
index 688ebbbf6e2..acfc0d8f0f0 100644
--- a/src/pl/plpython/plpy_procedure.c
+++ b/src/pl/plpython/plpy_procedure.c
@@ -291,8 +291,8 @@ PLy_procedure_create(PLyProcedure *proc,
 			}
 
 			/* Allocate arrays for per-input-argument data */
-			proc->argnames = (char **) palloc0_array(char *, proc->nargs);
-			proc->args = (PLyDatumToOb *) palloc0_array(PLyDatumToOb, proc->nargs);
+			proc->argnames = palloc0_array(char *, proc->nargs);
+			proc->args = palloc0_array(PLyDatumToOb, proc->nargs);
 
 			for (i = pos = 0; i < total; i++)
 			{
diff --git a/src/pl/plpython/plpy_spi.c b/src/pl/plpython/plpy_spi.c
index 4980873efcf..419e0a9b9ae 100644
--- a/src/pl/plpython/plpy_spi.c
+++ b/src/pl/plpython/plpy_spi.c
@@ -240,8 +240,8 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit)
 
 		if (nargs > 0)
 		{
-			values = (Datum *) palloc(nargs * sizeof(Datum));
-			nulls = (char *) palloc(nargs * sizeof(char));
+			values = palloc_array(Datum, nargs);
+			nulls = palloc_array(char, nargs);
 		}
 		else
 		{
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 85e83bbf1e3..42a72f1cb02 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -1597,8 +1597,8 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid,
 		prodesc->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
 		prodesc->fn_tid = procTup->t_self;
 		prodesc->nargs = procStruct->pronargs;
-		prodesc->arg_out_func = (FmgrInfo *) palloc0(prodesc->nargs * sizeof(FmgrInfo));
-		prodesc->arg_is_rowtype = (bool *) palloc0(prodesc->nargs * sizeof(bool));
+		prodesc->arg_out_func = palloc0_array(FmgrInfo, prodesc->nargs);
+		prodesc->arg_is_rowtype = palloc0_array(bool, prodesc->nargs);
 		MemoryContextSwitchTo(oldcontext);
 
 		/* Remember if function is STABLE/IMMUTABLE */
@@ -2673,9 +2673,9 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
 	qdesc = palloc0_object(pltcl_query_desc);
 	snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
 	qdesc->nargs = nargs;
-	qdesc->argtypes = (Oid *) palloc(nargs * sizeof(Oid));
-	qdesc->arginfuncs = (FmgrInfo *) palloc(nargs * sizeof(FmgrInfo));
-	qdesc->argtypioparams = (Oid *) palloc(nargs * sizeof(Oid));
+	qdesc->argtypes = palloc_array(Oid, nargs);
+	qdesc->arginfuncs = palloc_array(FmgrInfo, nargs);
+	qdesc->argtypioparams = palloc_array(Oid, nargs);
 	MemoryContextSwitchTo(oldcontext);
 
 	/************************************************************
@@ -3292,7 +3292,7 @@ pltcl_build_tuple_result(Tcl_Interp *interp, Tcl_Obj **kvObjv, int kvObjc,
 		attinmeta = NULL;
 	}
 
-	values = (char **) palloc0(tupdesc->natts * sizeof(char *));
+	values = palloc0_array(char *, tupdesc->natts);
 
 	if (kvObjc % 2 != 0)
 		ereport(ERROR,
diff --git a/src/test/modules/ldap_password_func/ldap_password_func.c b/src/test/modules/ldap_password_func/ldap_password_func.c
index f57bdf087c1..04312e63d24 100644
--- a/src/test/modules/ldap_password_func/ldap_password_func.c
+++ b/src/test/modules/ldap_password_func/ldap_password_func.c
@@ -39,7 +39,7 @@ rot13_passphrase(char *pw)
 {
 	size_t		size = strlen(pw) + 1;
 
-	char	   *new_pw = (char *) palloc(size);
+	char	   *new_pw = palloc_array(char, size);
 
 	strlcpy(new_pw, pw, size);
 	for (char *p = new_pw; *p; p++)
diff --git a/src/test/modules/plsample/plsample.c b/src/test/modules/plsample/plsample.c
index f294f5ca4ad..4c0b7d8ad66 100644
--- a/src/test/modules/plsample/plsample.c
+++ b/src/test/modules/plsample/plsample.c
@@ -142,7 +142,7 @@ plsample_func_handler(PG_FUNCTION_ARGS)
 									 "PL/Sample function",
 									 ALLOCSET_SMALL_SIZES);
 
-	arg_out_func = (FmgrInfo *) palloc0(fcinfo->nargs * sizeof(FmgrInfo));
+	arg_out_func = palloc0_array(FmgrInfo, fcinfo->nargs);
 	numargs = get_func_arg_info(pl_tuple, &argtypes, &argnames, &argmodes);
 
 	/*
diff --git a/src/test/modules/spgist_name_ops/spgist_name_ops.c b/src/test/modules/spgist_name_ops/spgist_name_ops.c
index 0c269740839..ac1e3958cbb 100644
--- a/src/test/modules/spgist_name_ops/spgist_name_ops.c
+++ b/src/test/modules/spgist_name_ops/spgist_name_ops.c
@@ -55,7 +55,7 @@ formTextDatum(const char *data, int datalen)
 {
 	char	   *p;
 
-	p = (char *) palloc(datalen + VARHDRSZ);
+	p = palloc_array(char, datalen + VARHDRSZ);
 
 	if (datalen + VARHDRSZ_SHORT <= VARATT_SHORT_MAX)
 	{
diff --git a/src/test/modules/test_aio/test_aio.c b/src/test/modules/test_aio/test_aio.c
index 6270775af7c..39d857557cf 100644
--- a/src/test/modules/test_aio/test_aio.c
+++ b/src/test/modules/test_aio/test_aio.c
@@ -715,11 +715,11 @@ read_buffers(PG_FUNCTION_ARGS)
 	InitMaterializedSRF(fcinfo, 0);
 
 	/* at worst each block gets its own IO */
-	operations = palloc0(sizeof(ReadBuffersOperation) * nblocks);
-	buffers = palloc0(sizeof(Buffer) * nblocks);
-	buffers_datum = palloc0(sizeof(Datum) * nblocks);
-	io_reqds = palloc0(sizeof(bool) * nblocks);
-	nblocks_per_io = palloc0(sizeof(int) * nblocks);
+	operations = palloc0_array(ReadBuffersOperation, nblocks);
+	buffers = palloc0_array(Buffer, nblocks);
+	buffers_datum = palloc0_array(Datum, nblocks);
+	io_reqds = palloc0_array(bool, nblocks);
+	nblocks_per_io = palloc0_array(int, nblocks);
 
 	rel = relation_open(relid, AccessShareLock);
 	smgr = RelationGetSmgr(rel);
diff --git a/src/test/modules/test_binaryheap/test_binaryheap.c b/src/test/modules/test_binaryheap/test_binaryheap.c
index 8ae0f46a932..99f846bcf93 100644
--- a/src/test/modules/test_binaryheap/test_binaryheap.c
+++ b/src/test/modules/test_binaryheap/test_binaryheap.c
@@ -49,7 +49,7 @@ get_max_from_heap(binaryheap *heap)
 static int *
 get_permutation(int size)
 {
-	int		   *permutation = (int *) palloc(size * sizeof(int));
+	int		   *permutation = palloc_array(int, size);
 
 	permutation[0] = 0;
 
diff --git a/src/test/modules/test_custom_types/test_custom_types.c b/src/test/modules/test_custom_types/test_custom_types.c
index 41262044b47..420f1ccd80c 100644
--- a/src/test/modules/test_custom_types/test_custom_types.c
+++ b/src/test/modules/test_custom_types/test_custom_types.c
@@ -58,7 +58,7 @@ Datum
 int_custom_out(PG_FUNCTION_ARGS)
 {
 	int32		arg1 = PG_GETARG_INT32(0);
-	char	   *result = (char *) palloc(12);	/* sign, 10 digits, '\0' */
+	char	   *result = palloc_array(char, 12);	/* sign, 10 digits, '\0' */
 
 	pg_ltoa(arg1, result);
 	PG_RETURN_CSTRING(result);
diff --git a/src/test/modules/test_integerset/test_integerset.c b/src/test/modules/test_integerset/test_integerset.c
index f24ee886eb0..dfbc90e5d05 100644
--- a/src/test/modules/test_integerset/test_integerset.c
+++ b/src/test/modules/test_integerset/test_integerset.c
@@ -147,7 +147,7 @@ test_pattern(const test_spec *spec)
 
 	/* Pre-process the pattern, creating an array of integers from it. */
 	patternlen = strlen(spec->pattern_str);
-	pattern_values = palloc(patternlen * sizeof(uint64));
+	pattern_values = palloc_array(uint64, patternlen);
 	pattern_num_values = 0;
 	for (int i = 0; i < patternlen; i++)
 	{
diff --git a/src/test/modules/test_radixtree/test_radixtree.c b/src/test/modules/test_radixtree/test_radixtree.c
index da2a47d3aad..6ffd24cd0df 100644
--- a/src/test/modules/test_radixtree/test_radixtree.c
+++ b/src/test/modules/test_radixtree/test_radixtree.c
@@ -319,7 +319,7 @@ test_random(void)
 
 	/* add some random values */
 	pg_prng_seed(&state, seed);
-	keys = (TestValueType *) palloc(sizeof(uint64) * num_keys);
+	keys = palloc_array(TestValueType, num_keys);
 	for (int i = 0; i < num_keys; i++)
 	{
 		uint64		key = pg_prng_uint64(&state) & filter;
diff --git a/src/test/modules/test_rbtree/test_rbtree.c b/src/test/modules/test_rbtree/test_rbtree.c
index 39c199c6760..f99ef11e7bd 100644
--- a/src/test/modules/test_rbtree/test_rbtree.c
+++ b/src/test/modules/test_rbtree/test_rbtree.c
@@ -96,7 +96,7 @@ GetPermutation(int size)
 	int		   *permutation;
 	int			i;
 
-	permutation = (int *) palloc(size * sizeof(int));
+	permutation = palloc_array(int, size);
 
 	permutation[0] = 0;
 
@@ -417,8 +417,8 @@ testdelete(int size, int delsize)
 	rbt_populate(tree, size, 1);
 
 	/* Choose unique ids to delete */
-	deleteIds = (int *) palloc(delsize * sizeof(int));
-	chosen = (bool *) palloc0(size * sizeof(bool));
+	deleteIds = palloc_array(int, delsize);
+	chosen = palloc0_array(bool, size);
 
 	for (i = 0; i < delsize; i++)
 	{
diff --git a/src/test/modules/test_regex/test_regex.c b/src/test/modules/test_regex/test_regex.c
index cfe569aa060..918c52c00b0 100644
--- a/src/test/modules/test_regex/test_regex.c
+++ b/src/test/modules/test_regex/test_regex.c
@@ -167,7 +167,7 @@ test_re_compile(text *text_re, int cflags, Oid collation,
 	char		errMsg[100];
 
 	/* Convert pattern string to wide characters */
-	pattern = (pg_wchar *) palloc((text_re_len + 1) * sizeof(pg_wchar));
+	pattern = palloc_array(pg_wchar, text_re_len + 1);
 	pattern_len = pg_mb2wchar_with_len(text_re_val,
 									   pattern,
 									   text_re_len);
diff --git a/src/test/modules/test_resowner/test_resowner_basic.c b/src/test/modules/test_resowner/test_resowner_basic.c
index c05f5ca11f3..c0891f7e539 100644
--- a/src/test/modules/test_resowner/test_resowner_basic.c
+++ b/src/test/modules/test_resowner/test_resowner_basic.c
@@ -64,7 +64,7 @@ test_resowner_priorities(PG_FUNCTION_ARGS)
 	parent = ResourceOwnerCreate(CurrentResourceOwner, "test parent");
 	child = ResourceOwnerCreate(parent, "test child");
 
-	before_desc = palloc(nkinds * sizeof(ResourceOwnerDesc));
+	before_desc = palloc_array(ResourceOwnerDesc, nkinds);
 	for (int i = 0; i < nkinds; i++)
 	{
 		before_desc[i].name = psprintf("test resource before locks %d", i);
@@ -73,7 +73,7 @@ test_resowner_priorities(PG_FUNCTION_ARGS)
 		before_desc[i].ReleaseResource = ReleaseString;
 		before_desc[i].DebugPrint = PrintString;
 	}
-	after_desc = palloc(nkinds * sizeof(ResourceOwnerDesc));
+	after_desc = palloc_array(ResourceOwnerDesc, nkinds);
 	for (int i = 0; i < nkinds; i++)
 	{
 		after_desc[i].name = psprintf("test resource after locks %d", i);
diff --git a/src/test/modules/test_resowner/test_resowner_many.c b/src/test/modules/test_resowner/test_resowner_many.c
index 4962b371bdc..4bb34ca7e4c 100644
--- a/src/test/modules/test_resowner/test_resowner_many.c
+++ b/src/test/modules/test_resowner/test_resowner_many.c
@@ -226,7 +226,7 @@ test_resowner_many(PG_FUNCTION_ARGS)
 		elog(ERROR, "nforget_al must between 0 and 'nremember_al'");
 
 	/* Initialize all the different resource kinds to use */
-	before_kinds = palloc(nkinds * sizeof(ManyTestResourceKind));
+	before_kinds = palloc_array(ManyTestResourceKind, nkinds);
 	for (int i = 0; i < nkinds; i++)
 	{
 		InitManyTestResourceKind(&before_kinds[i],
@@ -234,7 +234,7 @@ test_resowner_many(PG_FUNCTION_ARGS)
 								 RESOURCE_RELEASE_BEFORE_LOCKS,
 								 RELEASE_PRIO_FIRST + i);
 	}
-	after_kinds = palloc(nkinds * sizeof(ManyTestResourceKind));
+	after_kinds = palloc_array(ManyTestResourceKind, nkinds);
 	for (int i = 0; i < nkinds; i++)
 	{
 		InitManyTestResourceKind(&after_kinds[i],
diff --git a/src/test/modules/test_saslprep/test_saslprep.c b/src/test/modules/test_saslprep/test_saslprep.c
index 121212d4fa2..eb211b3d679 100644
--- a/src/test/modules/test_saslprep/test_saslprep.c
+++ b/src/test/modules/test_saslprep/test_saslprep.c
@@ -83,7 +83,7 @@ test_saslprep(PG_FUNCTION_ARGS)
 	/*
 	 * Copy the input given, to make SASLprep() act on a sanitized string.
 	 */
-	input_data = palloc0(src_len + 1);
+	input_data = palloc0_array(char, src_len + 1);
 	memcpy(input_data, src, src_len);
 	input_data[src_len] = '\0';
 
diff --git a/src/test/modules/test_tidstore/test_tidstore.c b/src/test/modules/test_tidstore/test_tidstore.c
index 60446e484d3..86200e99860 100644
--- a/src/test/modules/test_tidstore/test_tidstore.c
+++ b/src/test/modules/test_tidstore/test_tidstore.c
@@ -134,9 +134,9 @@ test_create(PG_FUNCTION_ARGS)
 
 	items.num_tids = 0;
 	items.max_tids = array_init_size / sizeof(ItemPointerData);
-	items.insert_tids = (ItemPointerData *) palloc0(array_init_size);
-	items.lookup_tids = (ItemPointerData *) palloc0(array_init_size);
-	items.iter_tids = (ItemPointerData *) palloc0(array_init_size);
+	items.insert_tids = palloc0_array(ItemPointerData, items.max_tids);
+	items.lookup_tids = palloc0_array(ItemPointerData, items.max_tids);
+	items.iter_tids = palloc0_array(ItemPointerData, items.max_tids);
 
 	MemoryContextSwitchTo(old_ctx);
 
diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c
index 9801cdd1d8c..22fda30b508 100644
--- a/src/test/regress/regress.c
+++ b/src/test/regress/regress.c
@@ -250,7 +250,7 @@ reverse_name(PG_FUNCTION_ARGS)
 	int			len;
 	char	   *new_string;
 
-	new_string = palloc0(NAMEDATALEN);
+	new_string = palloc0_array(char, NAMEDATALEN);
 	for (i = 0; i < NAMEDATALEN && string[i]; ++i)
 		;
 	if (i == NAMEDATALEN || !string[i])
@@ -294,7 +294,7 @@ Datum
 int44in(PG_FUNCTION_ARGS)
 {
 	char	   *input_string = PG_GETARG_CSTRING(0);
-	int32	   *result = (int32 *) palloc(4 * sizeof(int32));
+	int32	   *result = palloc_array(int32, 4);
 	int			i;
 
 	i = sscanf(input_string,
@@ -318,7 +318,7 @@ Datum
 int44out(PG_FUNCTION_ARGS)
 {
 	int32	   *an_array = (int32 *) PG_GETARG_POINTER(0);
-	char	   *result = (char *) palloc(16 * 4);
+	char	   *result = palloc_array(char, 16 * 4);
 
 	snprintf(result, 16 * 4, "%d,%d,%d,%d",
 			 an_array[0],
@@ -371,8 +371,8 @@ make_tuple_indirect(PG_FUNCTION_ARGS)
 	tuple.t_tableOid = InvalidOid;
 	tuple.t_data = rec;
 
-	values = (Datum *) palloc(ncolumns * sizeof(Datum));
-	nulls = (bool *) palloc(ncolumns * sizeof(bool));
+	values = palloc_array(Datum, ncolumns);
+	nulls = palloc_array(bool, ncolumns);
 
 	heap_deform_tuple(&tuple, tupdesc, values, nulls);
 
@@ -452,7 +452,7 @@ get_environ(PG_FUNCTION_ARGS)
 	for (char **s = environ; *s; s++)
 		nvals++;
 
-	env = palloc(nvals * sizeof(Datum));
+	env = palloc_array(Datum, nvals);
 
 	for (int i = 0; i < nvals; i++)
 		env[i] = CStringGetTextDatum(environ[i]);
@@ -1183,7 +1183,7 @@ test_text_to_wchars(PG_FUNCTION_ARGS)
 	text	   *string = PG_GETARG_TEXT_PP(1);
 	const char *data = VARDATA_ANY(string);
 	size_t		size = VARSIZE_ANY_EXHDR(string);
-	pg_wchar   *wchars = palloc(sizeof(pg_wchar) * (size + 1));
+	pg_wchar   *wchars = palloc_array(pg_wchar, size + 1);
 	Datum	   *datums;
 	int			wlen;
 	int			encoding;
@@ -1194,7 +1194,7 @@ test_text_to_wchars(PG_FUNCTION_ARGS)
 
 	if (size > 0)
 	{
-		datums = palloc(sizeof(Datum) * size);
+		datums = palloc_array(Datum, size);
 		wlen = pg_encoding_mb2wchar_with_len(encoding,
 											 data,
 											 wchars,
@@ -1237,7 +1237,7 @@ test_wchars_to_text(PG_FUNCTION_ARGS)
 
 	if (wlen > 0)
 	{
-		pg_wchar   *wchars = palloc(sizeof(pg_wchar) * wlen);
+		pg_wchar   *wchars = palloc_array(pg_wchar, wlen);
 
 		for (int i = 0; i < wlen; ++i)
 		{
-- 
Tristan Partin
https://tristan.partin.io

