From 5f74d499bfc07c43f44d0989aab6b23c6b5bfbb0 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 17 Jun 1999 22:21:41 +0000
Subject: [PATCH] Defend against function calls with more than 8 arguments
 (code used to overrun its fixed-size arrays before detecting error; not
 cool). Also, replace uses of magic constant '8' with 'MAXFARGS'.

---
 src/backend/parser/parse_coerce.c |  7 ++++---
 src/backend/parser/parse_func.c   | 34 ++++++++++++++++++-------------
 src/backend/parser/parse_target.c |  6 +++---
 src/include/parser/parse_func.h   |  9 +++++---
 4 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index 9e0e77b051b..1563a0eef73 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.17 1999/05/29 03:17:19 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.18 1999/06/17 22:21:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,6 +20,7 @@
 #include "parser/parse_expr.h"
 
 #include "catalog/pg_type.h"
+#include "parser/parse_func.h"
 #include "parser/parse_type.h"
 #include "parser/parse_target.h"
 #include "parser/parse_coerce.h"
@@ -132,7 +133,7 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids)
 	HeapTuple	ftup;
 	int			i;
 	Type		tp;
-	Oid			oid_array[8];
+	Oid			oid_array[MAXFARGS];
 
 	/* run through argument list... */
 	for (i = 0; i < nargs; i++)
@@ -160,7 +161,7 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids)
 			 */
 			else if (input_typeids[i] != UNKNOWNOID)
 			{
-				MemSet(&oid_array[0], 0, 8 * sizeof(Oid));
+				MemSet(oid_array, 0, MAXFARGS * sizeof(Oid));
 				oid_array[0] = input_typeids[i];
 
 				/*
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 8fa8fb8b365..6f676618474 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.46 1999/05/25 16:10:17 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.47 1999/06/17 22:21:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -83,8 +83,6 @@ static Oid	agg_select_candidate(Oid typeid, CandidateList candidates);
 
 #define ISCOMPLEX(type) (typeidTypeRelid(type) ? true : false)
 
-#define MAXFARGS 8				/* max # args to a c or postquel function */
-
 typedef struct _SuperQE
 {
 	Oid			sqe_relid;
@@ -241,9 +239,9 @@ Node *
 ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
 				  int *curr_resno, int precedence)
 {
-	Oid			rettype = (Oid) 0;
-	Oid			argrelid = (Oid) 0;
-	Oid			funcid = (Oid) 0;
+	Oid			rettype = InvalidOid;
+	Oid			argrelid = InvalidOid;
+	Oid			funcid = InvalidOid;
 	List	   *i = NIL;
 	Node	   *first_arg = NULL;
 	char	   *relname = NULL;
@@ -252,12 +250,12 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
 	Oid			relid;
 	int			nargs;
 	Func	   *funcnode;
-	Oid			oid_array[8];
+	Oid			oid_array[MAXFARGS];
 	Oid		   *true_oid_array;
 	Node	   *retval;
 	bool		retset;
 	bool		attisset = false;
-	Oid			toid = (Oid) 0;
+	Oid			toid = InvalidOid;
 	Expr	   *expr;
 
 	if (fargs)
@@ -425,7 +423,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
 	 * transform relation name arguments into varnodes of the appropriate
 	 * form.
 	 */
-	MemSet(&oid_array[0], 0, 8 * sizeof(Oid));
+	MemSet(oid_array, 0, MAXFARGS * sizeof(Oid));
 
 	nargs = 0;
 	foreach(i, fargs)
@@ -477,6 +475,14 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
 				toid = exprType(pair);
 		}
 
+		/* Most of the rest of the parser just assumes that functions do not
+		 * have more than MAXFARGS parameters.  We have to test here to protect
+		 * against array overruns, etc.
+		 */
+		if (nargs >= MAXFARGS)
+			elog(ERROR, "Cannot pass more than %d arguments to a function",
+				 MAXFARGS);
+
 		oid_array[nargs++] = toid;
 	}
 
@@ -638,7 +644,7 @@ static Oid
 funcid_get_rettype(Oid funcid)
 {
 	HeapTuple	func_tuple = NULL;
-	Oid			funcrettype = (Oid) 0;
+	Oid			funcrettype = InvalidOid;
 
 	func_tuple = SearchSysCacheTuple(PROOID,
 									 ObjectIdGetDatum(funcid),
@@ -701,8 +707,8 @@ func_get_candidates(char *funcname, int nargs)
 					current_candidate = (CandidateList)
 						palloc(sizeof(struct _CandidateList));
 					current_candidate->args = (Oid *)
-						palloc(8 * sizeof(Oid));
-					MemSet(current_candidate->args, 0, 8 * sizeof(Oid));
+						palloc(MAXFARGS * sizeof(Oid));
+					MemSet(current_candidate->args, 0, MAXFARGS * sizeof(Oid));
 					for (i = 0; i < nargs; i++)
 						current_candidate->args[i] = pgProcP->proargtypes[i];
 
@@ -1337,7 +1343,7 @@ setup_tlist(char *attname, Oid relid)
 						 type_mod,
 						 get_attname(relid, attno),
 						 0,
-						 (Oid) 0,
+						 InvalidOid,
 						 false);
 	varnode = makeVar(-1, attno, typeid, type_mod, 0, -1, attno);
 
@@ -1362,7 +1368,7 @@ setup_base_tlist(Oid typeid)
 						 -1,
 						 "<noname>",
 						 0,
-						 (Oid) 0,
+						 InvalidOid,
 						 false);
 	varnode = makeVar(-1, 1, typeid, -1, 0, -1, 1);
 	tle = makeTargetEntry(resnode, (Node *) varnode);
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 563a48e1b4e..09f624fc760 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.41 1999/05/29 03:17:20 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.42 1999/06/17 22:21:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -712,7 +712,7 @@ SizeTargetExpr(ParseState *pstate,
 	int			i;
 	HeapTuple	ftup;
 	char	   *funcname;
-	Oid			oid_array[8];
+	Oid			oid_array[MAXFARGS];
 
 	FuncCall   *func;
 	A_Const    *cons;
@@ -720,7 +720,7 @@ SizeTargetExpr(ParseState *pstate,
 	funcname = typeidTypeName(attrtype);
 	oid_array[0] = attrtype;
 	oid_array[1] = INT4OID;
-	for (i = 2; i < 8; i++)
+	for (i = 2; i < MAXFARGS; i++)
 		oid_array[i] = InvalidOid;
 
 	/* attempt to find with arguments exactly as specified... */
diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h
index b83929358c5..d3441a0ce89 100644
--- a/src/include/parser/parse_func.h
+++ b/src/include/parser/parse_func.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_func.h,v 1.15 1999/05/25 16:14:27 momjian Exp $
+ * $Id: parse_func.h,v 1.16 1999/06/17 22:21:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,6 +20,9 @@
 #include <parser/parse_func.h>
 #include <parser/parse_node.h>
 
+
+#define MAXFARGS 8				/* max # args to a c or postquel function */
+
 /*
  *	This structure is used to explore the inheritance hierarchy above
  *	nodes in the type tree in order to disambiguate among polymorphic
@@ -47,7 +50,7 @@ extern Node *ParseNestedFuncOrColumn(ParseState *pstate, Attr *attr,
 extern Node *ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
 				  int *curr_resno, int precedence);
 
-extern void
-			func_error(char *caller, char *funcname, int nargs, Oid *argtypes, char *msg);
+extern void func_error(char *caller, char *funcname,
+					   int nargs, Oid *argtypes, char *msg);
 
 #endif	 /* PARSE_FUNC_H */
-- 
GitLab