From b4cc35fbb709bd6fcae8998f041fd731c9acbf42 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 31 Jul 2017 11:33:46 -0400
Subject: [PATCH] Tighten coding for non-composite case in plperl's
 return_next.

Coverity complained about this code's practice of using scalar variables
as single-element arrays.  While that's really just nitpicking, it probably
is more readable to declare them as arrays, so let's do that.  A more
important point is that the code was just blithely assuming that the
result tupledesc has exactly one column; if it doesn't, we'd likely get
a crash of some sort in tuplestore_putvalues.  Since the tupledesc is
manufactured outside of plperl, that seems like an uncomfortably long
chain of assumptions.  We can nail it down at little cost with a sanity
check earlier in the function.
---
 src/pl/plperl/plperl.c | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index b10b4434aa7..afebec910d6 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -3247,12 +3247,18 @@ plperl_return_next_internal(SV *sv)
 
 		/*
 		 * This is the first call to return_next in the current PL/Perl
-		 * function call, so memoize some lookups
+		 * function call, so identify the output tuple descriptor and create a
+		 * tuplestore to hold the result rows.
 		 */
 		if (prodesc->fn_retistuple)
 			(void) get_call_result_type(fcinfo, NULL, &tupdesc);
 		else
+		{
 			tupdesc = rsi->expectedDesc;
+			/* Protect assumption below that we return exactly one column */
+			if (tupdesc == NULL || tupdesc->natts != 1)
+				elog(ERROR, "expected single-column result descriptor for non-composite SETOF result");
+		}
 
 		/*
 		 * Make sure the tuple_store and ret_tdesc are sufficiently
@@ -3300,20 +3306,20 @@ plperl_return_next_internal(SV *sv)
 	}
 	else
 	{
-		Datum		ret;
-		bool		isNull;
+		Datum		ret[1];
+		bool		isNull[1];
 
-		ret = plperl_sv_to_datum(sv,
-								 prodesc->result_oid,
-								 -1,
-								 fcinfo,
-								 &prodesc->result_in_func,
-								 prodesc->result_typioparam,
-								 &isNull);
+		ret[0] = plperl_sv_to_datum(sv,
+									prodesc->result_oid,
+									-1,
+									fcinfo,
+									&prodesc->result_in_func,
+									prodesc->result_typioparam,
+									&isNull[0]);
 
 		tuplestore_putvalues(current_call_data->tuple_store,
 							 current_call_data->ret_tdesc,
-							 &ret, &isNull);
+							 ret, isNull);
 	}
 
 	MemoryContextSwitchTo(old_cxt);
-- 
GitLab