Some modest cleanups I've accumulated.
>From 9c5846cc3f04c6797696a234fac0953815e09e4b Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryz...@telsasoft.com>
Date: Sun, 23 Oct 2022 14:52:48 -0500
Subject: [PATCH 1/6] WIP: do not loop to set an array to false

See also:
9fd45870c1436b477264c0c82eb195df52bc0919
572e3e6634e55accf95e2bcfb1340019c86a21dc
---
 src/backend/access/transam/xlogprefetcher.c |  5 +---
 src/backend/catalog/pg_constraint.c         | 11 ++------
 src/backend/commands/user.c                 |  6 +----
 src/backend/statistics/extended_stats.c     |  6 +----
 src/backend/storage/smgr/md.c               |  3 +--
 src/backend/tcop/pquery.c                   |  3 +--
 src/backend/utils/adt/arrayfuncs.c          | 29 ++++++++-------------
 src/test/isolation/isolationtester.c        |  3 +--
 8 files changed, 19 insertions(+), 47 deletions(-)

diff --git a/src/backend/access/transam/xlogprefetcher.c b/src/backend/access/transam/xlogprefetcher.c
index 0cf03945eec..7fcfd146525 100644
--- a/src/backend/access/transam/xlogprefetcher.c
+++ b/src/backend/access/transam/xlogprefetcher.c
@@ -832,13 +832,10 @@ pg_stat_get_recovery_prefetch(PG_FUNCTION_ARGS)
 #define PG_STAT_GET_RECOVERY_PREFETCH_COLS 10
 	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
 	Datum		values[PG_STAT_GET_RECOVERY_PREFETCH_COLS];
-	bool		nulls[PG_STAT_GET_RECOVERY_PREFETCH_COLS];
+	bool		nulls[PG_STAT_GET_RECOVERY_PREFETCH_COLS] = {0};
 
 	InitMaterializedSRF(fcinfo, 0);
 
-	for (int i = 0; i < PG_STAT_GET_RECOVERY_PREFETCH_COLS; ++i)
-		nulls[i] = false;
-
 	values[0] = TimestampTzGetDatum(pg_atomic_read_u64(&SharedStats->reset_time));
 	values[1] = Int64GetDatum(pg_atomic_read_u64(&SharedStats->prefetch));
 	values[2] = Int64GetDatum(pg_atomic_read_u64(&SharedStats->hit));
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 3a5d4e96439..bd8f32bf62d 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -82,8 +82,8 @@ CreateConstraintEntry(const char *constraintName,
 	Relation	conDesc;
 	Oid			conOid;
 	HeapTuple	tup;
-	bool		nulls[Natts_pg_constraint];
-	Datum		values[Natts_pg_constraint];
+	bool		nulls[Natts_pg_constraint] = {0};
+	Datum		values[Natts_pg_constraint] = {0};
 	ArrayType  *conkeyArray;
 	ArrayType  *confkeyArray;
 	ArrayType  *conpfeqopArray;
@@ -165,13 +165,6 @@ CreateConstraintEntry(const char *constraintName,
 	else
 		conexclopArray = NULL;
 
-	/* initialize nulls and values */
-	for (i = 0; i < Natts_pg_constraint; i++)
-	{
-		nulls[i] = false;
-		values[i] = (Datum) NULL;
-	}
-
 	conOid = GetNewOidWithIndex(conDesc, ConstraintOidIndexId,
 								Anum_pg_constraint_oid);
 	values[Anum_pg_constraint_oid - 1] = ObjectIdGetDatum(conOid);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 8b6543edee2..5af79792136 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -1234,8 +1234,7 @@ RenameRole(const char *oldname, const char *newname)
 	bool		isnull;
 	Datum		repl_val[Natts_pg_authid];
 	bool		repl_null[Natts_pg_authid];
-	bool		repl_repl[Natts_pg_authid];
-	int			i;
+	bool		repl_repl[Natts_pg_authid] = {0};
 	Oid			roleid;
 	ObjectAddress address;
 	Form_pg_authid authform;
@@ -1321,9 +1320,6 @@ RenameRole(const char *oldname, const char *newname)
 	}
 
 	/* OK, construct the modified tuple */
-	for (i = 0; i < Natts_pg_authid; i++)
-		repl_repl[i] = false;
-
 	repl_repl[Anum_pg_authid_rolname - 1] = true;
 	repl_val[Anum_pg_authid_rolname - 1] = DirectFunctionCall1(namein,
 															   CStringGetDatum(newname));
diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c
index ab97e71dd79..93a9d3eeafb 100644
--- a/src/backend/statistics/extended_stats.c
+++ b/src/backend/statistics/extended_stats.c
@@ -2343,7 +2343,7 @@ serialize_expr_stats(AnlExprData *exprdata, int nexprs)
 		VacAttrStats *stats = exprdata[exprno].vacattrstat;
 
 		Datum		values[Natts_pg_statistic];
-		bool		nulls[Natts_pg_statistic];
+		bool		nulls[Natts_pg_statistic] = {0};
 		HeapTuple	stup;
 
 		if (!stats->stats_valid)
@@ -2359,10 +2359,6 @@ serialize_expr_stats(AnlExprData *exprdata, int nexprs)
 		/*
 		 * Construct a new pg_statistic tuple
 		 */
-		for (i = 0; i < Natts_pg_statistic; ++i)
-		{
-			nulls[i] = false;
-		}
 
 		values[Anum_pg_statistic_starelid - 1] = ObjectIdGetDatum(InvalidOid);
 		values[Anum_pg_statistic_staattnum - 1] = Int16GetDatum(InvalidAttrNumber);
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index 14b6fa0fd90..2d5cc97eaa9 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -557,8 +557,7 @@ void
 mdopen(SMgrRelation reln)
 {
 	/* mark it not open */
-	for (int forknum = 0; forknum <= MAX_FORKNUM; forknum++)
-		reln->md_num_open_segs[forknum] = 0;
+	memset(reln->md_num_open_segs, 0, (1+MAX_FORKNUM) * sizeof(*reln->md_num_open_segs));
 }
 
 /*
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index 52e2db6452b..53b712fd3b5 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -653,8 +653,7 @@ PortalSetResultFormat(Portal portal, int nFormats, int16 *formats)
 	else
 	{
 		/* use default format for all columns */
-		for (i = 0; i < natts; i++)
-			portal->formats[i] = 0;
+		memset(portal->formats, 0, natts * sizeof(*portal->formats));
 	}
 }
 
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 495e449a9e9..ff62eb01dfd 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -1038,7 +1038,7 @@ array_out(PG_FUNCTION_ARGS)
 				i,
 				j,
 				k,
-				indx[MAXDIM];
+				indx[MAXDIM] = {0};
 	int			ndim,
 			   *dims,
 			   *lb;
@@ -1203,8 +1203,7 @@ array_out(PG_FUNCTION_ARGS)
 	if (needdims)
 		APPENDSTR(dims_str);
 	APPENDCHAR('{');
-	for (i = 0; i < ndim; i++)
-		indx[i] = 0;
+
 	j = 0;
 	k = 0;
 	do
@@ -4988,10 +4987,9 @@ array_slice_size(char *arraydataptr, bits8 *arraynullsptr,
 				span[MAXDIM],
 				prod[MAXDIM],
 				dist[MAXDIM],
-				indx[MAXDIM];
+				indx[MAXDIM] = {0};
 	char	   *ptr;
-	int			i,
-				j,
+	int			j,
 				inc;
 	int			count = 0;
 
@@ -5007,8 +5005,7 @@ array_slice_size(char *arraydataptr, bits8 *arraynullsptr,
 					 typlen, typbyval, typalign);
 	mda_get_prod(ndim, dim, prod);
 	mda_get_offset_values(ndim, dist, prod, span);
-	for (i = 0; i < ndim; i++)
-		indx[i] = 0;
+
 	j = ndim - 1;
 	do
 	{
@@ -5059,9 +5056,8 @@ array_extract_slice(ArrayType *newarray,
 				prod[MAXDIM],
 				span[MAXDIM],
 				dist[MAXDIM],
-				indx[MAXDIM];
-	int			i,
-				j,
+				indx[MAXDIM] = {0};
+	int			j,
 				inc;
 
 	src_offset = ArrayGetOffset(ndim, dim, lb, st);
@@ -5070,8 +5066,7 @@ array_extract_slice(ArrayType *newarray,
 	mda_get_prod(ndim, dim, prod);
 	mda_get_range(ndim, span, st, endp);
 	mda_get_offset_values(ndim, dist, prod, span);
-	for (i = 0; i < ndim; i++)
-		indx[i] = 0;
+
 	dest_offset = 0;
 	j = ndim - 1;
 	do
@@ -5138,9 +5133,8 @@ array_insert_slice(ArrayType *destArray,
 				prod[MAXDIM],
 				span[MAXDIM],
 				dist[MAXDIM],
-				indx[MAXDIM];
-	int			i,
-				j,
+				indx[MAXDIM] = {0};
+	int			j,
 				inc;
 
 	dest_offset = ArrayGetOffset(ndim, dim, lb, st);
@@ -5156,8 +5150,7 @@ array_insert_slice(ArrayType *destArray,
 	mda_get_prod(ndim, dim, prod);
 	mda_get_range(ndim, span, st, endp);
 	mda_get_offset_values(ndim, dist, prod, span);
-	for (i = 0; i < ndim; i++)
-		indx[i] = 0;
+
 	src_offset = 0;
 	j = ndim - 1;
 	do
diff --git a/src/test/isolation/isolationtester.c b/src/test/isolation/isolationtester.c
index 0a66235153a..19808c59892 100644
--- a/src/test/isolation/isolationtester.c
+++ b/src/test/isolation/isolationtester.c
@@ -432,8 +432,7 @@ run_all_permutations(TestSpec *testspec)
 	 * already picked from this pile.
 	 */
 	piles = pg_malloc(sizeof(int) * testspec->nsessions);
-	for (i = 0; i < testspec->nsessions; i++)
-		piles[i] = 0;
+	memset(piles, 0, sizeof(*piles) * testspec->nsessions);
 
 	run_all_permutations_recurse(testspec, piles, 0, stepptrs);
 
-- 
2.25.1

>From cc9f9b8b878b4d878b0aa4f04226cb6c2873275e Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryz...@telsasoft.com>
Date: Fri, 14 Jan 2022 19:25:21 -0600
Subject: [PATCH 2/6] Avoid the most useless instances of nulls[0]=false..

Getting rid of more of these is apparently too controvercial, but these are the
cases where 1) nulls is always being set to false; and, 2) values[] is not
being memset, so there's no parallel between the two.
---
 contrib/sslinfo/sslinfo.c                |  5 +-
 src/backend/replication/logical/origin.c | 13 +---
 src/backend/utils/adt/misc.c             |  7 +--
 src/backend/utils/misc/pg_controldata.c  | 80 ++----------------------
 4 files changed, 10 insertions(+), 95 deletions(-)

diff --git a/contrib/sslinfo/sslinfo.c b/contrib/sslinfo/sslinfo.c
index 5fd46b98741..d9edfe1b742 100644
--- a/contrib/sslinfo/sslinfo.c
+++ b/contrib/sslinfo/sslinfo.c
@@ -424,7 +424,7 @@ ssl_extension_info(PG_FUNCTION_ARGS)
 	if (call_cntr < max_calls)
 	{
 		Datum		values[3];
-		bool		nulls[3];
+		bool		nulls[3] = {0};
 		char	   *buf;
 		HeapTuple	tuple;
 		Datum		result;
@@ -453,7 +453,6 @@ ssl_extension_info(PG_FUNCTION_ARGS)
 					 errmsg("unknown OpenSSL extension in certificate at position %d",
 							call_cntr)));
 		values[0] = CStringGetTextDatum(OBJ_nid2sn(nid));
-		nulls[0] = false;
 
 		/* Get the extension value */
 		if (X509V3_EXT_print(membuf, ext, 0, 0) <= 0)
@@ -463,11 +462,9 @@ ssl_extension_info(PG_FUNCTION_ARGS)
 							call_cntr)));
 		len = BIO_get_mem_data(membuf, &buf);
 		values[1] = PointerGetDatum(cstring_to_text_with_len(buf, len));
-		nulls[1] = false;
 
 		/* Get critical status */
 		values[2] = BoolGetDatum(X509_EXTENSION_get_critical(ext));
-		nulls[2] = false;
 
 		/* Build tuple */
 		tuple = heap_form_tuple(fctx->tupdesc, values, nulls);
diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c
index f134e44878f..adb3430c33a 100644
--- a/src/backend/replication/logical/origin.c
+++ b/src/backend/replication/logical/origin.c
@@ -1527,10 +1527,9 @@ pg_show_replication_origin_status(PG_FUNCTION_ARGS)
 			continue;
 
 		memset(values, 0, sizeof(values));
-		memset(nulls, 1, sizeof(nulls));
+		memset(nulls, 0, sizeof(nulls));
 
 		values[0] = ObjectIdGetDatum(state->roident);
-		nulls[0] = false;
 
 		/*
 		 * We're not preventing the origin to be dropped concurrently, so
@@ -1538,19 +1537,13 @@ pg_show_replication_origin_status(PG_FUNCTION_ARGS)
 		 */
 		if (replorigin_by_oid(state->roident, true,
 							  &roname))
-		{
 			values[1] = CStringGetTextDatum(roname);
-			nulls[1] = false;
-		}
+		else
+			nulls[1] = true;
 
 		LWLockAcquire(&state->lock, LW_SHARED);
-
 		values[2] = LSNGetDatum(state->remote_lsn);
-		nulls[2] = false;
-
 		values[3] = LSNGetDatum(state->local_lsn);
-		nulls[3] = false;
-
 		LWLockRelease(&state->lock);
 
 		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index 9c132512315..611b492624a 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -246,7 +246,7 @@ pg_tablespace_databases(PG_FUNCTION_ARGS)
 		char	   *subdir;
 		bool		isempty;
 		Datum		values[1];
-		bool		nulls[1];
+		bool		nulls[1] = {0};
 
 		/* this test skips . and .., but is awfully weak */
 		if (!datOid)
@@ -262,7 +262,6 @@ pg_tablespace_databases(PG_FUNCTION_ARGS)
 			continue;			/* indeed, nothing in it */
 
 		values[0] = ObjectIdGetDatum(datOid);
-		nulls[0] = false;
 
 		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
 							 values, nulls);
@@ -530,11 +529,9 @@ pg_get_catalog_foreign_keys(PG_FUNCTION_ARGS)
 	{
 		const SysFKRelationship *fkrel = &sys_fk_relationships[funcctx->call_cntr];
 		Datum		values[6];
-		bool		nulls[6];
+		bool		nulls[6] = {0};
 		HeapTuple	tuple;
 
-		memset(nulls, false, sizeof(nulls));
-
 		values[0] = ObjectIdGetDatum(fkrel->fk_table);
 		values[1] = FunctionCall3(arrayinp,
 								  CStringGetDatum(fkrel->fk_columns),
diff --git a/src/backend/utils/misc/pg_controldata.c b/src/backend/utils/misc/pg_controldata.c
index 781f8b87580..32be2b4b5d8 100644
--- a/src/backend/utils/misc/pg_controldata.c
+++ b/src/backend/utils/misc/pg_controldata.c
@@ -32,7 +32,7 @@ Datum
 pg_control_system(PG_FUNCTION_ARGS)
 {
 	Datum		values[4];
-	bool		nulls[4];
+	bool		nulls[4] = {0};
 	TupleDesc	tupdesc;
 	HeapTuple	htup;
 	ControlFileData *ControlFile;
@@ -60,16 +60,9 @@ pg_control_system(PG_FUNCTION_ARGS)
 				(errmsg("calculated CRC checksum does not match value stored in file")));
 
 	values[0] = Int32GetDatum(ControlFile->pg_control_version);
-	nulls[0] = false;
-
 	values[1] = Int32GetDatum(ControlFile->catalog_version_no);
-	nulls[1] = false;
-
 	values[2] = Int64GetDatum(ControlFile->system_identifier);
-	nulls[2] = false;
-
 	values[3] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->time));
-	nulls[3] = false;
 
 	htup = heap_form_tuple(tupdesc, values, nulls);
 
@@ -80,7 +73,7 @@ Datum
 pg_control_checkpoint(PG_FUNCTION_ARGS)
 {
 	Datum		values[18];
-	bool		nulls[18];
+	bool		nulls[18] = {0};
 	TupleDesc	tupdesc;
 	HeapTuple	htup;
 	ControlFileData *ControlFile;
@@ -147,60 +140,25 @@ pg_control_checkpoint(PG_FUNCTION_ARGS)
 
 	/* Populate the values and null arrays */
 	values[0] = LSNGetDatum(ControlFile->checkPoint);
-	nulls[0] = false;
-
 	values[1] = LSNGetDatum(ControlFile->checkPointCopy.redo);
-	nulls[1] = false;
-
 	values[2] = CStringGetTextDatum(xlogfilename);
-	nulls[2] = false;
-
 	values[3] = Int32GetDatum(ControlFile->checkPointCopy.ThisTimeLineID);
-	nulls[3] = false;
-
 	values[4] = Int32GetDatum(ControlFile->checkPointCopy.PrevTimeLineID);
-	nulls[4] = false;
-
 	values[5] = BoolGetDatum(ControlFile->checkPointCopy.fullPageWrites);
-	nulls[5] = false;
-
 	values[6] = CStringGetTextDatum(psprintf("%u:%u",
 											 EpochFromFullTransactionId(ControlFile->checkPointCopy.nextXid),
 											 XidFromFullTransactionId(ControlFile->checkPointCopy.nextXid)));
-	nulls[6] = false;
-
 	values[7] = ObjectIdGetDatum(ControlFile->checkPointCopy.nextOid);
-	nulls[7] = false;
-
 	values[8] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMulti);
-	nulls[8] = false;
-
 	values[9] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMultiOffset);
-	nulls[9] = false;
-
 	values[10] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestXid);
-	nulls[10] = false;
-
 	values[11] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestXidDB);
-	nulls[11] = false;
-
 	values[12] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestActiveXid);
-	nulls[12] = false;
-
 	values[13] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestMulti);
-	nulls[13] = false;
-
 	values[14] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestMultiDB);
-	nulls[14] = false;
-
 	values[15] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestCommitTsXid);
-	nulls[15] = false;
-
 	values[16] = TransactionIdGetDatum(ControlFile->checkPointCopy.newestCommitTsXid);
-	nulls[16] = false;
-
 	values[17] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->checkPointCopy.time));
-	nulls[17] = false;
 
 	htup = heap_form_tuple(tupdesc, values, nulls);
 
@@ -211,7 +169,7 @@ Datum
 pg_control_recovery(PG_FUNCTION_ARGS)
 {
 	Datum		values[5];
-	bool		nulls[5];
+	bool		nulls[5] = {0};
 	TupleDesc	tupdesc;
 	HeapTuple	htup;
 	ControlFileData *ControlFile;
@@ -241,19 +199,10 @@ pg_control_recovery(PG_FUNCTION_ARGS)
 				(errmsg("calculated CRC checksum does not match value stored in file")));
 
 	values[0] = LSNGetDatum(ControlFile->minRecoveryPoint);
-	nulls[0] = false;
-
 	values[1] = Int32GetDatum(ControlFile->minRecoveryPointTLI);
-	nulls[1] = false;
-
 	values[2] = LSNGetDatum(ControlFile->backupStartPoint);
-	nulls[2] = false;
-
 	values[3] = LSNGetDatum(ControlFile->backupEndPoint);
-	nulls[3] = false;
-
 	values[4] = BoolGetDatum(ControlFile->backupEndRequired);
-	nulls[4] = false;
 
 	htup = heap_form_tuple(tupdesc, values, nulls);
 
@@ -264,7 +213,7 @@ Datum
 pg_control_init(PG_FUNCTION_ARGS)
 {
 	Datum		values[11];
-	bool		nulls[11];
+	bool		nulls[11] = {0};
 	TupleDesc	tupdesc;
 	HeapTuple	htup;
 	ControlFileData *ControlFile;
@@ -306,37 +255,16 @@ pg_control_init(PG_FUNCTION_ARGS)
 				(errmsg("calculated CRC checksum does not match value stored in file")));
 
 	values[0] = Int32GetDatum(ControlFile->maxAlign);
-	nulls[0] = false;
-
 	values[1] = Int32GetDatum(ControlFile->blcksz);
-	nulls[1] = false;
-
 	values[2] = Int32GetDatum(ControlFile->relseg_size);
-	nulls[2] = false;
-
 	values[3] = Int32GetDatum(ControlFile->xlog_blcksz);
-	nulls[3] = false;
-
 	values[4] = Int32GetDatum(ControlFile->xlog_seg_size);
-	nulls[4] = false;
-
 	values[5] = Int32GetDatum(ControlFile->nameDataLen);
-	nulls[5] = false;
-
 	values[6] = Int32GetDatum(ControlFile->indexMaxKeys);
-	nulls[6] = false;
-
 	values[7] = Int32GetDatum(ControlFile->toast_max_chunk_size);
-	nulls[7] = false;
-
 	values[8] = Int32GetDatum(ControlFile->loblksize);
-	nulls[8] = false;
-
 	values[9] = BoolGetDatum(ControlFile->float8ByVal);
-	nulls[9] = false;
-
 	values[10] = Int32GetDatum(ControlFile->data_checksum_version);
-	nulls[10] = false;
 
 	htup = heap_form_tuple(tupdesc, values, nulls);
 
-- 
2.25.1

>From 54dfbc7d0081de75546003b4c401785127921168 Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryz...@telsasoft.com>
Date: Sat, 25 Sep 2021 18:58:33 -0500
Subject: [PATCH 3/6] selfuncs.c: refactor parent ACL check

The code for statistics expressions was copied from indexes, and this
un-copies it.  selfuncs.c is 8k lines long, and this makes it 30 LOC shorter.

See prior discussion:
f97a5902-b4d1-77da-8d2f-6b5b2094f...@enterprisedb.com

Tomas said there's similar code elsewhere, and I saw
examine_simple_variable() and ruleutils.c, but I'm unable to find
anything else similar close enough to share.
---
 src/backend/utils/adt/selfuncs.c | 140 ++++++++++++-------------------
 1 file changed, 52 insertions(+), 88 deletions(-)

diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index e0aeaa69092..a9f3ccf9a30 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -188,6 +188,8 @@ static char *convert_string_datum(Datum value, Oid typid, Oid collid,
 								  bool *failure);
 static double convert_timevalue_to_scalar(Datum value, Oid typid,
 										  bool *failure);
+static void recheck_parent_acl(PlannerInfo *root, VariableStatData *vardata,
+								Oid relid);
 static void examine_simple_variable(PlannerInfo *root, Var *var,
 									VariableStatData *vardata);
 static bool get_variable_range(PlannerInfo *root, VariableStatData *vardata,
@@ -5174,51 +5176,7 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
 									(pg_class_aclcheck(rte->relid, userid,
 													   ACL_SELECT) == ACLCHECK_OK);
 
-								/*
-								 * If the user doesn't have permissions to
-								 * access an inheritance child relation, check
-								 * the permissions of the table actually
-								 * mentioned in the query, since most likely
-								 * the user does have that permission.  Note
-								 * that whole-table select privilege on the
-								 * parent doesn't quite guarantee that the
-								 * user could read all columns of the child.
-								 * But in practice it's unlikely that any
-								 * interesting security violation could result
-								 * from allowing access to the expression
-								 * index's stats, so we allow it anyway.  See
-								 * similar code in examine_simple_variable()
-								 * for additional comments.
-								 */
-								if (!vardata->acl_ok &&
-									root->append_rel_array != NULL)
-								{
-									AppendRelInfo *appinfo;
-									Index		varno = index->rel->relid;
-
-									appinfo = root->append_rel_array[varno];
-									while (appinfo &&
-										   planner_rt_fetch(appinfo->parent_relid,
-															root)->rtekind == RTE_RELATION)
-									{
-										varno = appinfo->parent_relid;
-										appinfo = root->append_rel_array[varno];
-									}
-									if (varno != index->rel->relid)
-									{
-										/* Repeat access check on this rel */
-										rte = planner_rt_fetch(varno, root);
-										Assert(rte->rtekind == RTE_RELATION);
-
-										userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
-
-										vardata->acl_ok =
-											rte->securityQuals == NIL &&
-											(pg_class_aclcheck(rte->relid,
-															   userid,
-															   ACL_SELECT) == ACLCHECK_OK);
-									}
-								}
+								recheck_parent_acl(root, vardata, index->rel->relid);
 							}
 							else
 							{
@@ -5308,49 +5266,7 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
 						(pg_class_aclcheck(rte->relid, userid,
 										   ACL_SELECT) == ACLCHECK_OK);
 
-					/*
-					 * If the user doesn't have permissions to access an
-					 * inheritance child relation, check the permissions of
-					 * the table actually mentioned in the query, since most
-					 * likely the user does have that permission.  Note that
-					 * whole-table select privilege on the parent doesn't
-					 * quite guarantee that the user could read all columns of
-					 * the child. But in practice it's unlikely that any
-					 * interesting security violation could result from
-					 * allowing access to the expression stats, so we allow it
-					 * anyway.  See similar code in examine_simple_variable()
-					 * for additional comments.
-					 */
-					if (!vardata->acl_ok &&
-						root->append_rel_array != NULL)
-					{
-						AppendRelInfo *appinfo;
-						Index		varno = onerel->relid;
-
-						appinfo = root->append_rel_array[varno];
-						while (appinfo &&
-							   planner_rt_fetch(appinfo->parent_relid,
-												root)->rtekind == RTE_RELATION)
-						{
-							varno = appinfo->parent_relid;
-							appinfo = root->append_rel_array[varno];
-						}
-						if (varno != onerel->relid)
-						{
-							/* Repeat access check on this rel */
-							rte = planner_rt_fetch(varno, root);
-							Assert(rte->rtekind == RTE_RELATION);
-
-							userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
-
-							vardata->acl_ok =
-								rte->securityQuals == NIL &&
-								(pg_class_aclcheck(rte->relid,
-												   userid,
-												   ACL_SELECT) == ACLCHECK_OK);
-						}
-					}
-
+					recheck_parent_acl(root, vardata, onerel->relid);
 					break;
 				}
 
@@ -5360,6 +5276,54 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
 	}
 }
 
+/*
+ * If the user doesn't have permissions to access an inheritance child
+ * relation, check the permissions of the table actually mentioned in the
+ * query, since most likely the user does have that permission.  Note that
+ * whole-table select privilege on the parent doesn't quite guarantee that the
+ * user could read all columns of the child.  But in practice it's unlikely
+ * that any interesting security violation could result from allowing access to
+ * the index or expression stats, so we allow it anyway.  See similar code in
+ * examine_simple_variable() for additional comments.
+ */
+static void
+recheck_parent_acl(PlannerInfo *root, VariableStatData *vardata, Oid relid)
+{
+	RangeTblEntry	*rte;
+	Oid		userid;
+
+	if (!vardata->acl_ok &&
+		root->append_rel_array != NULL)
+	{
+		AppendRelInfo *appinfo;
+		Index		varno = relid;
+
+		appinfo = root->append_rel_array[varno];
+		while (appinfo &&
+			   planner_rt_fetch(appinfo->parent_relid,
+								root)->rtekind == RTE_RELATION)
+		{
+			varno = appinfo->parent_relid;
+			appinfo = root->append_rel_array[varno];
+		}
+
+		if (varno != relid)
+		{
+			/* Repeat access check on this rel */
+			rte = planner_rt_fetch(varno, root);
+			Assert(rte->rtekind == RTE_RELATION);
+
+			userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
+
+			vardata->acl_ok =
+				rte->securityQuals == NIL &&
+				(pg_class_aclcheck(rte->relid,
+								   userid,
+								   ACL_SELECT) == ACLCHECK_OK);
+		}
+	}
+}
+
 /*
  * examine_simple_variable
  *		Handle a simple Var for examine_variable
-- 
2.25.1

>From 28ffc13ceab70b9e05aa3563b0b8b37e209a349e Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryz...@telsasoft.com>
Date: Thu, 25 Nov 2021 22:47:41 -0600
Subject: [PATCH 4/6] move beentry++ away from the middle of the loop body

This was more reasonable when the "if" block was shorter; but, now it's
large, and the variable increment is easy to miss, as happened during
patch development:
https://www.postgresql.org/message-id/20211202040653.gm17...@telsasoft.com
---
 src/backend/utils/activity/backend_status.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 1146a6c33cd..1cf2bc58410 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -842,7 +842,6 @@ pgstat_read_current_status(void)
 			CHECK_FOR_INTERRUPTS();
 		}
 
-		beentry++;
 		/* Only valid entries get included into the local array */
 		if (localentry->backendStatus.st_procpid > 0)
 		{
@@ -869,6 +868,8 @@ pgstat_read_current_status(void)
 #endif
 			localNumBackends++;
 		}
+
+		beentry++;
 	}
 
 	/* Set the pointer only after completion of a valid table */
-- 
2.25.1

>From 51e25dc00d811965c6e72d1914bd03035d9797fe Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryz...@telsasoft.com>
Date: Tue, 22 Nov 2022 18:44:23 -0600
Subject: [PATCH 5/6] conjunction is cleaner and shorter than nested
 conditionals

---
 src/backend/replication/pgoutput/pgoutput.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index 2ecaa5b9074..2ec201e3007 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -810,7 +810,7 @@ pgoutput_row_filter_exec_expr(ExprState *state, ExprContext *econtext)
 	ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
 
 	elog(DEBUG3, "row filter evaluates to %s (isnull: %s)",
-		 isnull ? "false" : DatumGetBool(ret) ? "true" : "false",
+		 !isnull && DatumGetBool(ret) ? "true" : "false",
 		 isnull ? "true" : "false");
 
 	if (isnull)
-- 
2.25.1

>From f3c4c2cf735c448edd66e9f0f546547355aff1c1 Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryz...@telsasoft.com>
Date: Wed, 13 Jul 2022 15:06:21 -0500
Subject: [PATCH 6/6] basebackup: use port/strlcpy()

---
 src/bin/pg_basebackup/pg_basebackup.c | 3 +--
 src/bin/pg_basebackup/pg_receivewal.c | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
index 22836ca01a1..28960158e7f 100644
--- a/src/bin/pg_basebackup/pg_basebackup.c
+++ b/src/bin/pg_basebackup/pg_basebackup.c
@@ -1005,8 +1005,7 @@ parse_compress_options(char *option, char **algorithm, char **detail,
 		char	   *alg;
 
 		alg = palloc((sep - option) + 1);
-		memcpy(alg, option, sep - option);
-		alg[sep - option] = '\0';
+		strlcpy(alg, option, sep - option + 1);
 
 		*algorithm = alg;
 		*detail = pstrdup(sep + 1);
diff --git a/src/bin/pg_basebackup/pg_receivewal.c b/src/bin/pg_basebackup/pg_receivewal.c
index 63207ca025e..3acf19a1201 100644
--- a/src/bin/pg_basebackup/pg_receivewal.c
+++ b/src/bin/pg_basebackup/pg_receivewal.c
@@ -161,8 +161,7 @@ parse_compress_options(char *option, char **algorithm, char **detail)
 		char	   *alg;
 
 		alg = palloc((sep - option) + 1);
-		memcpy(alg, option, sep - option);
-		alg[sep - option] = '\0';
+		strlcpy(alg, option, sep - option + 1);
 
 		*algorithm = alg;
 		*detail = pstrdup(sep + 1);
-- 
2.25.1

Reply via email to