From daf0113128eab7a55baf53fc676f863fba3914e8 Mon Sep 17 00:00:00 2001
From: Tatsuo Ishii <ishii@postgresql.org>
Date: Tue, 7 Oct 2025 11:22:51 +0900
Subject: [PATCH v2] Fix Coverity issues reported in commit 25a30bbd423.

This commit fixes several issues pointed out by Coverity.

- In row_is_in_frame(), return value of window_gettupleslot() was not
  checked.

- WinGetFuncArgInPartition() tried to derefference "isout" pointer
  even if it's NULL in some places.

Moreover, in WinGetFuncArgInPartition refactor the do...while loop so
that the codes inside the loop simpler. Also simplify the case when
abs_pos < 0.

Discussion: https://postgr.es/m/202510051612.gw67jlc2iqpw%40alvherre.pgsql
---
 src/backend/executor/nodeWindowAgg.c | 77 ++++++++++++++--------------
 1 file changed, 38 insertions(+), 39 deletions(-)

diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index cf667c81211..0698aae37a7 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -1501,8 +1501,9 @@ row_is_in_frame(WindowObject winobj, int64 pos, TupleTableSlot *slot,
 			/* following row that is not peer is out of frame */
 			if (pos > winstate->currentpos)
 			{
-				if (fetch_tuple)
-					window_gettupleslot(winobj, pos, slot);
+				if (fetch_tuple)	/* need to fetch tuple? */
+					if (!window_gettupleslot(winobj, pos, slot))
+						return -1;
 				if (!are_peers(winstate, slot, winstate->ss.ss_ScanTupleSlot))
 					return -1;
 			}
@@ -3721,6 +3722,7 @@ WinGetFuncArgInPartition(WindowObject winobj, int argno,
 	int			notnull_offset;
 	int			notnull_relpos;
 	int			forward;
+	bool		myisout;
 
 	Assert(WindowObjectIsValid(winobj));
 	winstate = winobj->winstate;
@@ -3759,63 +3761,60 @@ WinGetFuncArgInPartition(WindowObject winobj, int argno,
 
 	if (!null_treatment)		/* IGNORE NULLS is not specified */
 	{
+		/* get tupple and evaluate in a partition */
 		datum = gettuple_eval_partition(winobj, argno,
-										abs_pos, isnull, isout);
-		if (!*isout && set_mark)
+										abs_pos, isnull, &myisout);
+		if (!myisout && set_mark)
 			WinSetMarkPosition(winobj, abs_pos);
+		if (isout)
+			*isout = myisout;
 		return datum;
 	}
 
+	myisout = false;
+	datum = 0;
+
 	/*
 	 * Get the next nonnull value in the partition, moving forward or backward
 	 * until we find a value or reach the partition's end.
 	 */
 	do
 	{
+		int			nn_info;	/* NOT NULL info */
+
 		abs_pos += forward;
-		if (abs_pos < 0)
-		{
-			/* out of partition */
-			if (isout)
-				*isout = true;
-			*isnull = true;
-			datum = 0;
+		if (abs_pos < 0)		/* apparently out of partition */
 			break;
-		}
 
-		switch (get_notnull_info(winobj, abs_pos))
+		/* check NOT NULL cached info */
+		nn_info = get_notnull_info(winobj, abs_pos);
+		if (nn_info == NN_NOTNULL)	/* this row is known to be NOT NULL */
+			notnull_offset++;
+
+		else if (nn_info == NN_NULL)	/* this row is known to be NULL */
+			continue;			/* keep on moving forward or backward */
+
+		else					/* need to check NULL or not */
 		{
-			case NN_NOTNULL:	/* this row is known to be NOT NULL */
-				notnull_offset++;
-				if (notnull_offset >= notnull_relpos)
-				{
-					/* prepare to exit this loop */
-					datum = gettuple_eval_partition(winobj, argno,
-													abs_pos, isnull, isout);
-				}
-				break;
-			case NN_NULL:		/* this row is known to be NULL */
-				if (isout)
-					*isout = false;
-				*isnull = true;
-				datum = 0;
-				break;
-			default:			/* need to check NULL or not */
-				datum = gettuple_eval_partition(winobj, argno,
-												abs_pos, isnull, isout);
-				if (*isout)		/* out of partition? */
-					return datum;
-
-				if (!*isnull)
-					notnull_offset++;
-				/* record the row status */
-				put_notnull_info(winobj, abs_pos, *isnull);
+			/* get tupple and evaluate in a partition */
+			datum = gettuple_eval_partition(winobj, argno,
+											abs_pos, isnull, &myisout);
+			if (myisout)		/* out of partition? */
 				break;
+			if (!*isnull)
+				notnull_offset++;
+			/* record the row status */
+			put_notnull_info(winobj, abs_pos, *isnull);
 		}
 	} while (notnull_offset < notnull_relpos);
 
-	if (!*isout && set_mark)
+	/* get tupple and evaluate in a partition */
+	datum = gettuple_eval_partition(winobj, argno,
+									abs_pos, isnull, &myisout);
+	if (!myisout && set_mark)
 		WinSetMarkPosition(winobj, abs_pos);
+	if (isout)
+		*isout = myisout;
 
 	return datum;
 }
-- 
2.43.0

