From be3aa30da3624995b7cbf67b44314f693c2d15bf Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sat, 9 Jul 2005 01:53:22 +0000
Subject: [PATCH] Fix inadequate error checking: you can't assume that
 fcinfo->resultinfo is a ReturnSetInfo unless you've tested it with IsA.

---
 contrib/tablefunc/tablefunc.c | 40 +++++++++++++++---------------
 contrib/xml2/xpath.c          | 46 ++++++++++++++++++-----------------
 2 files changed, 45 insertions(+), 41 deletions(-)

diff --git a/contrib/tablefunc/tablefunc.c b/contrib/tablefunc/tablefunc.c
index 6ab79ebeff3..97163c81a40 100644
--- a/contrib/tablefunc/tablefunc.c
+++ b/contrib/tablefunc/tablefunc.c
@@ -687,9 +687,13 @@ crosstab_hash(PG_FUNCTION_ARGS)
 	int			num_categories;
 
 	/* check to see if caller supports us returning a tuplestore */
-	if (!rsinfo || !(rsinfo->allowedModes & SFRM_Materialize))
+	if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
 		ereport(ERROR,
-				(errcode(ERRCODE_SYNTAX_ERROR),
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("set-valued function called in context that cannot accept a set")));
+	if (!(rsinfo->allowedModes & SFRM_Materialize))
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("materialize mode required, but it is not " \
 						"allowed in this context")));
 
@@ -1049,9 +1053,13 @@ connectby_text(PG_FUNCTION_ARGS)
 	MemoryContext oldcontext;
 
 	/* check to see if caller supports us returning a tuplestore */
-	if (!rsinfo || !(rsinfo->allowedModes & SFRM_Materialize))
+	if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
 		ereport(ERROR,
-				(errcode(ERRCODE_SYNTAX_ERROR),
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("set-valued function called in context that cannot accept a set")));
+	if (!(rsinfo->allowedModes & SFRM_Materialize))
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("materialize mode required, but it is not " \
 						"allowed in this context")));
 
@@ -1076,13 +1084,6 @@ connectby_text(PG_FUNCTION_ARGS)
 	/* OK, use it then */
 	attinmeta = TupleDescGetAttInMetadata(tupdesc);
 
-	/* check to see if caller supports us returning a tuplestore */
-	if (!rsinfo || !(rsinfo->allowedModes & SFRM_Materialize))
-		ereport(ERROR,
-				(errcode(ERRCODE_SYNTAX_ERROR),
-				 errmsg("materialize mode required, but it is not " \
-						"allowed in this context")));
-
 	/* OK, go to work */
 	rsinfo->returnMode = SFRM_Materialize;
 	rsinfo->setResult = connectby(relname,
@@ -1131,9 +1132,15 @@ connectby_text_serial(PG_FUNCTION_ARGS)
 	MemoryContext oldcontext;
 
 	/* check to see if caller supports us returning a tuplestore */
-	if (!rsinfo || !(rsinfo->allowedModes & SFRM_Materialize))
-		elog(ERROR, "connectby: materialize mode required, but it is not "
-			 "allowed in this context");
+	if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("set-valued function called in context that cannot accept a set")));
+	if (!(rsinfo->allowedModes & SFRM_Materialize))
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("materialize mode required, but it is not " \
+						"allowed in this context")));
 
 	if (fcinfo->nargs == 7)
 	{
@@ -1156,11 +1163,6 @@ connectby_text_serial(PG_FUNCTION_ARGS)
 	/* OK, use it then */
 	attinmeta = TupleDescGetAttInMetadata(tupdesc);
 
-	/* check to see if caller supports us returning a tuplestore */
-	if (!rsinfo->allowedModes & SFRM_Materialize)
-		elog(ERROR, "connectby requires Materialize mode, but it is not "
-			 "allowed in this context");
-
 	/* OK, go to work */
 	rsinfo->returnMode = SFRM_Materialize;
 	rsinfo->setResult = connectby(relname,
diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index c15a5bb6225..98a5e3a0e20 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -669,23 +669,36 @@ xpath_table(PG_FUNCTION_ARGS)
 
 	StringInfo	querysql;
 
-/* We only have a valid tuple description in table function mode */
+	/* We only have a valid tuple description in table function mode */
+	if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("set-valued function called in context that cannot accept a set")));
 	if (rsinfo->expectedDesc == NULL)
-	{
-		ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR),
-			  errmsg("xpath_table must be called as a table function")));
-	}
+		ereport(ERROR,
+				(errcode(ERRCODE_SYNTAX_ERROR),
+				 errmsg("xpath_table must be called as a table function")));
 
-/* The tuplestore must exist in a higher context than
- * this function call (per_query_ctx is used) */
+	/*
+	 * We want to materialise because it means that we don't have to carry
+	 * libxml2 parser state between invocations of this function
+	 */
+	if (!(rsinfo->allowedModes & SFRM_Materialize))
+		ereport(ERROR,
+				(errcode(ERRCODE_SYNTAX_ERROR),
+				 errmsg("xpath_table requires Materialize mode, but it is not "
+						"allowed in this context")));
+
+	/* The tuplestore must exist in a higher context than
+	 * this function call (per_query_ctx is used)
+	 */
 
 	per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
 	oldcontext = MemoryContextSwitchTo(per_query_ctx);
 
-/* Create the tuplestore - work_mem is the max in-memory size before a
- * file is created on disk to hold it.
- */
-
+	/* Create the tuplestore - work_mem is the max in-memory size before a
+	 * file is created on disk to hold it.
+	 */
 	tupstore = tuplestore_begin_heap(true, false, work_mem);
 
 	MemoryContextSwitchTo(oldcontext);
@@ -703,17 +716,6 @@ xpath_table(PG_FUNCTION_ARGS)
 
 	attinmeta = TupleDescGetAttInMetadata(ret_tupdesc);
 
-	/*
-	 * We want to materialise because it means that we don't have to carry
-	 * libxml2 parser state between invocations of this function
-	 */
-
-	/* check to see if caller supports us returning a tuplestore */
-	if (!rsinfo || !(rsinfo->allowedModes & SFRM_Materialize))
-		ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR),
-		   errmsg("xpath_table requires Materialize mode, but it is not "
-				  "allowed in this context")));
-
 	/* Set return mode and allocate value space. */
 	rsinfo->returnMode = SFRM_Materialize;
 	rsinfo->setDesc = ret_tupdesc;
-- 
GitLab