]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Tighten up the sanity checks in TypeCreate(): pass-by-value types must have
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 3 Aug 2008 15:23:58 +0000 (15:23 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 3 Aug 2008 15:23:58 +0000 (15:23 +0000)
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

index a6aec623cad11df419af716515ea62250a577f4e..a43ebec60268c065e6c0aa2705ad0d264781eb2d 100644 (file)
@@ -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)