From d1af54cf6d28e1e2cffe12a390ec7df88bae8b12 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter_e@gmx.net>
Date: Sat, 19 May 2001 09:28:08 +0000
Subject: [PATCH] Make sure fmgr_info() fills in fn_oid last, so that no
 partially initialized FmgrInfo structs linger after elog.

---
 src/backend/utils/fmgr/fmgr.c | 35 ++++++++++++++++++++++-------------
 1 file changed, 22 insertions(+), 13 deletions(-)

diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 08c35327d02..090807129f5 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.51 2001/03/22 03:59:59 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.52 2001/05/19 09:28:08 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -57,8 +57,8 @@ typedef struct
 } Oldstyle_fnextra;
 
 
-static void fmgr_info_C_lang(FmgrInfo *finfo, HeapTuple procedureTuple);
-static void fmgr_info_other_lang(FmgrInfo *finfo, HeapTuple procedureTuple);
+static void fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple);
+static void fmgr_info_other_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple);
 static Datum fmgr_oldstyle(PG_FUNCTION_ARGS);
 static Datum fmgr_untrusted(PG_FUNCTION_ARGS);
 
@@ -123,7 +123,11 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
 	Form_pg_proc procedureStruct;
 	char	   *prosrc;
 
-	finfo->fn_oid = functionId;
+	/*
+	 * fn_oid *must* be filled in last.  Code may assume that is fn_oid is valid,
+	 * the whole struct is valid.  Some FmgrInfo struct's do survive elogs.
+	 */
+	finfo->fn_oid = InvalidOid;
 	finfo->fn_extra = NULL;
 	finfo->fn_mcxt = CurrentMemoryContext;
 
@@ -138,6 +142,7 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
 		finfo->fn_strict = fbp->strict;
 		finfo->fn_retset = fbp->retset;
 		finfo->fn_addr = fbp->func;
+		finfo->fn_oid = functionId;
 		return;
 	}
 
@@ -158,6 +163,7 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
 	{
 		/* This isn't really supported anymore... */
 		finfo->fn_addr = fmgr_untrusted;
+		finfo->fn_oid = functionId;
 		ReleaseSysCache(procedureTuple);
 		return;
 	}
@@ -187,7 +193,7 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
 			break;
 
 		case ClanguageId:
-			fmgr_info_C_lang(finfo, procedureTuple);
+			fmgr_info_C_lang(functionId, finfo, procedureTuple);
 			break;
 
 		case SQLlanguageId:
@@ -195,18 +201,20 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
 			break;
 
 		default:
-			fmgr_info_other_lang(finfo, procedureTuple);
+			fmgr_info_other_lang(functionId, finfo, procedureTuple);
 			break;
 	}
 
+	finfo->fn_oid = functionId;
 	ReleaseSysCache(procedureTuple);
 }
 
 /*
- * Special fmgr_info processing for C-language functions
+ * Special fmgr_info processing for C-language functions.  Note that
+ * finfo->fn_oid is not valid yet.
  */
 static void
-fmgr_info_C_lang(FmgrInfo *finfo, HeapTuple procedureTuple)
+fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
 {
 	Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
 	Datum		prosrcattr,
@@ -224,14 +232,14 @@ fmgr_info_C_lang(FmgrInfo *finfo, HeapTuple procedureTuple)
 								 Anum_pg_proc_prosrc, &isnull);
 	if (isnull)
 		elog(ERROR, "fmgr: Could not extract prosrc for %u from pg_proc",
-			 finfo->fn_oid);
+			 functionId);
 	prosrcstring = DatumGetCString(DirectFunctionCall1(textout, prosrcattr));
 
 	probinattr = SysCacheGetAttr(PROCOID, procedureTuple,
 								 Anum_pg_proc_probin, &isnull);
 	if (isnull)
 		elog(ERROR, "fmgr: Could not extract probin for %u from pg_proc",
-			 finfo->fn_oid);
+			 functionId);
 	probinstring = DatumGetCString(DirectFunctionCall1(textout, probinattr));
 
 	/* Look up the function itself */
@@ -276,10 +284,11 @@ fmgr_info_C_lang(FmgrInfo *finfo, HeapTuple procedureTuple)
 }
 
 /*
- * Special fmgr_info processing for other-language functions
+ * Special fmgr_info processing for other-language functions.  Note
+ * that finfo->fn_oid is not valid yet.
  */
 static void
-fmgr_info_other_lang(FmgrInfo *finfo, HeapTuple procedureTuple)
+fmgr_info_other_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
 {
 	Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
 	Oid			language = procedureStruct->prolang;
@@ -312,7 +321,7 @@ fmgr_info_other_lang(FmgrInfo *finfo, HeapTuple procedureTuple)
 	else
 	{
 		elog(ERROR, "fmgr_info: function %u: unsupported language %u",
-			 finfo->fn_oid, language);
+			 functionId, language);
 	}
 	ReleaseSysCache(languageTuple);
 }
-- 
GitLab