From 82a1f0995337bb771b61955c959c5f624340ec5b Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun, 3 Aug 2008 15:23:58 +0000
Subject: [PATCH] Tighten up the sanity checks in TypeCreate(): pass-by-value
 types must have a size that is one of the supported values, not just anything
 <= sizeof(Datum). Cross-check the alignment specification against size as
 well.

---
 src/backend/catalog/pg_type.c | 71 +++++++++++++++++++++++++++++++----
 1 file changed, 64 insertions(+), 7 deletions(-)

diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index a6aec623cad..a43ebec6026 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.120 2008/07/30 17:05:04 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.121 2008/08/03 15:23:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -213,8 +213,7 @@ TypeCreate(Oid newTypeOid,
 	 * not check for bad combinations.
 	 *
 	 * Validate size specifications: either positive (fixed-length) or -1
-	 * (varlena) or -2 (cstring).  Pass-by-value types must have a fixed
-	 * length not more than sizeof(Datum).
+	 * (varlena) or -2 (cstring).
 	 */
 	if (!(internalSize > 0 ||
 		  internalSize == -1 ||
@@ -223,12 +222,70 @@ TypeCreate(Oid newTypeOid,
 				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 				 errmsg("invalid type internal size %d",
 						internalSize)));
-	if (passedByValue &&
-		(internalSize <= 0 || internalSize > (int16) sizeof(Datum)))
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+
+	if (passedByValue)
+	{
+		/*
+		 * Pass-by-value types must have a fixed length that is one of the
+		 * values supported by fetch_att() and store_att_byval(); and the
+		 * alignment had better agree, too.  All this code must match
+		 * access/tupmacs.h!
+		 */
+		if (internalSize == (int16) sizeof(char))
+		{
+			if (alignment != 'c')
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+						 errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
+								alignment, internalSize)));
+		}
+		else if (internalSize == (int16) sizeof(int16))
+		{
+			if (alignment != 's')
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+						 errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
+								alignment, internalSize)));
+		}
+		else if (internalSize == (int16) sizeof(int32))
+		{
+			if (alignment != 'i')
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+						 errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
+								alignment, internalSize)));
+		}
+#if SIZEOF_DATUM == 8
+		else if (internalSize == (int16) sizeof(Datum))
+		{
+			if (alignment != 'd')
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+						 errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
+								alignment, internalSize)));
+		}
+#endif
+		else
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 			   errmsg("internal size %d is invalid for passed-by-value type",
 					  internalSize)));
+	}
+	else
+	{
+		/* varlena types must have int align or better */
+		if (internalSize == -1 && !(alignment == 'i' || alignment == 'd'))
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+					 errmsg("alignment \"%c\" is invalid for variable-length type",
+							alignment)));
+		/* cstring must have char alignment */
+		if (internalSize == -2 && !(alignment == 'c'))
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+					 errmsg("alignment \"%c\" is invalid for variable-length type",
+							alignment)));
+	}
 
 	/* Only varlena types can be toasted */
 	if (storage != 'p' && internalSize != -1)
-- 
GitLab