diff --git a/doc/src/sgml/ref/create_aggregate.sgml b/doc/src/sgml/ref/create_aggregate.sgml
index 3df3303..c630850 100644
--- a/doc/src/sgml/ref/create_aggregate.sgml
+++ b/doc/src/sgml/ref/create_aggregate.sgml
@@ -472,9 +472,15 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
      <para>
       Deserializes a previously serialized aggregate state back into
       <replaceable class="PARAMETER">state_data_type</replaceable>. This
-      function must take a single argument of <replaceable class="PARAMETER">
-      serialtype</replaceable> and return <replaceable class="PARAMETER">
-      state_data_type</replaceable>.
+      function must take a two arguments, the first of which should be of type
+      <replaceable class="PARAMETER">serialtype</replaceable> and the second
+      must be of type <literal>INTERNAL</>. The return type must be
+      <replaceable class="PARAMETER">state_data_type</replaceable>. The second
+      argument serves no purpose other than to allow users to define their own
+      <replaceable class="PARAMETER">deserialfunc</replaceable> as the
+      creation of functions which return <literal>INTERNAL</> and contain no
+      <literal>INTERNAL</> arguments is disallowed by
+      <productname>PostgreSQL</productname>.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index 73d19ec..6e17e90 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -462,13 +462,17 @@ AggregateCreate(const char *aggName,
 
 	/*
 	 * Validate the deserialization function, if present. We must ensure that
-	 * the return type of this function is the same as the transType.
+	 * the return type of this function is the same as the transType. The 2nd
+	 * argument of the deserialization function is a dummy and only exists as
+	 * CREATE FUNCTION is disallowed for functions returning INTERNAL which
+	 * don't have any INTERNAL arguments.
 	 */
 	if (aggdeserialfnName)
 	{
 		fnArgs[0] = aggSerialType;
+		fnArgs[1] = INTERNALOID; /* dummy */
 
-		deserialfn = lookup_agg_function(aggdeserialfnName, 1,
+		deserialfn = lookup_agg_function(aggdeserialfnName, 2,
 										 fnArgs, variadicArgType,
 										 &rettype);
 
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 7b282de..5dee66f 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -998,6 +998,16 @@ combine_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
 				dsinfo->argnull[0] = slot->tts_isnull[0];
 
 				/*
+				 * The 2nd argument of the deserial function is merely a dummy
+				 * which serves only to allow users to create their own
+				 * deserial functions. CREATE FUNCTION disallows the creation
+				 * of functions returning an INTERNAL if the function does not
+				 * have any INTERNAL typed arguments.
+				 */
+				dsinfo->arg[1] = (Datum) 0;
+				dsinfo->argnull[1] = true;
+
+				/*
 				 * We run the deserialization functions in per-input-tuple
 				 * memory context.
 				 */
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 6a65e77..ad84135 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -2451,11 +2451,11 @@ DATA(insert OID = 3337 (  numeric_avg_combine	 PGNSP PGUID 12 1 0 0 0 f f f f f
 DESCR("aggregate combine function");
 DATA(insert OID = 2740 (  numeric_avg_serialize    PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "2281" _null_ _null_ _null_ _null_ _null_ numeric_avg_serialize _null_ _null_ _null_ ));
 DESCR("aggregate serial function");
-DATA(insert OID = 2741 (  numeric_avg_deserialize	 PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 2281 "17" _null_ _null_ _null_ _null_ _null_ numeric_avg_deserialize _null_ _null_ _null_ ));
+DATA(insert OID = 2741 (  numeric_avg_deserialize	 PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2281 "17 2281" _null_ _null_ _null_ _null_ _null_ numeric_avg_deserialize _null_ _null_ _null_ ));
 DESCR("aggregate deserial function");
 DATA(insert OID = 3335 (  numeric_serialize    PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "2281" _null_ _null_ _null_ _null_ _null_ numeric_serialize _null_ _null_ _null_ ));
 DESCR("aggregate serial function");
-DATA(insert OID = 3336 (  numeric_deserialize	 PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 2281 "17" _null_ _null_ _null_ _null_ _null_ numeric_deserialize _null_ _null_ _null_ ));
+DATA(insert OID = 3336 (  numeric_deserialize	 PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2281 "17 2281" _null_ _null_ _null_ _null_ _null_ numeric_deserialize _null_ _null_ _null_ ));
 DESCR("aggregate deserial function");
 DATA(insert OID = 3548 (  numeric_accum_inv    PGNSP PGUID 12 1 0 0 0 f f f f f f i s 2 0 2281 "2281 1700" _null_ _null_ _null_ _null_ _null_ numeric_accum_inv _null_ _null_ _null_ ));
 DESCR("aggregate transition function");
@@ -2469,7 +2469,7 @@ DATA(insert OID = 3338 (  numeric_poly_combine	  PGNSP PGUID 12 1 0 0 0 f f f f
 DESCR("aggregate combine function");
 DATA(insert OID = 3339 (  numeric_poly_serialize	PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "2281" _null_ _null_ _null_ _null_ _null_ numeric_poly_serialize _null_ _null_ _null_ ));
 DESCR("aggregate serial function");
-DATA(insert OID = 3340 (  numeric_poly_deserialize	  PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 2281 "17" _null_ _null_ _null_ _null_ _null_ numeric_poly_deserialize _null_ _null_ _null_ ));
+DATA(insert OID = 3340 (  numeric_poly_deserialize	  PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2281 "17 2281" _null_ _null_ _null_ _null_ _null_ numeric_poly_deserialize _null_ _null_ _null_ ));
 DESCR("aggregate deserial function");
 DATA(insert OID = 2746 (  int8_avg_accum	   PGNSP PGUID 12 1 0 0 0 f f f f f f i s 2 0 2281 "2281 20" _null_ _null_ _null_ _null_ _null_ int8_avg_accum _null_ _null_ _null_ ));
 DESCR("aggregate transition function");
@@ -2485,7 +2485,7 @@ DATA(insert OID = 2785 (  int8_avg_combine	  PGNSP PGUID 12 1 0 0 0 f f f f f f
 DESCR("aggregate combine function");
 DATA(insert OID = 2786 (  int8_avg_serialize	PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 17 "2281" _null_ _null_ _null_ _null_ _null_ int8_avg_serialize _null_ _null_ _null_ ));
 DESCR("aggregate serial function");
-DATA(insert OID = 2787 (  int8_avg_deserialize	  PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 2281 "17" _null_ _null_ _null_ _null_ _null_ int8_avg_deserialize _null_ _null_ _null_ ));
+DATA(insert OID = 2787 (  int8_avg_deserialize	  PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2281 "17 2281" _null_ _null_ _null_ _null_ _null_ int8_avg_deserialize _null_ _null_ _null_ ));
 DESCR("aggregate deserial function");
 DATA(insert OID = 3324 (  int4_avg_combine	  PGNSP PGUID 12 1 0 0 0 f f f f f f i s 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ _null_ int4_avg_combine _null_ _null_ _null_ ));
 DESCR("aggregate combine function");
diff --git a/src/test/regress/expected/create_aggregate.out b/src/test/regress/expected/create_aggregate.out
index 625dae5..642e365 100644
--- a/src/test/regress/expected/create_aggregate.out
+++ b/src/test/regress/expected/create_aggregate.out
@@ -145,7 +145,7 @@ CREATE AGGREGATE myavg (numeric)
 	serialfunc = numeric_avg_serialize,
 	deserialfunc = numeric_avg_serialize
 );
-ERROR:  function numeric_avg_serialize(bytea) does not exist
+ERROR:  function numeric_avg_serialize(bytea, internal) does not exist
 -- ensure return type of serialfunc is checked
 CREATE AGGREGATE myavg (numeric)
 (
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index b159640..cfbe10c 100644
--- a/src/test/regress/expected/opr_sanity.out
+++ b/src/test/regress/expected/opr_sanity.out
@@ -279,21 +279,15 @@ ORDER BY 1, 2;
 -- Look for functions that return type "internal" and do not have any
 -- "internal" argument.  Such a function would be a security hole since
 -- it might be used to call an internal function from an SQL command.
--- As of 7.3 this query should find internal_in, and as of 9.6 aggregate
--- deserialization will be found too. These should contain a runtime check to
--- ensure they can only be called in an aggregate context.
+-- As of 7.3 this query should find only internal_in.
 SELECT p1.oid, p1.proname
 FROM pg_proc as p1
 WHERE p1.prorettype = 'internal'::regtype AND NOT
     'internal'::regtype = ANY (p1.proargtypes);
- oid  |         proname          
-------+--------------------------
- 2741 | numeric_avg_deserialize
- 3336 | numeric_deserialize
- 3340 | numeric_poly_deserialize
- 2787 | int8_avg_deserialize
+ oid  |   proname   
+------+-------------
  2304 | internal_in
-(5 rows)
+(1 row)
 
 -- Look for functions that return a polymorphic type and do not have any
 -- polymorphic argument.  Calls of such functions would be unresolvable
diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql
index 62c84d0..fb70d26 100644
--- a/src/test/regress/sql/opr_sanity.sql
+++ b/src/test/regress/sql/opr_sanity.sql
@@ -228,9 +228,7 @@ ORDER BY 1, 2;
 -- Look for functions that return type "internal" and do not have any
 -- "internal" argument.  Such a function would be a security hole since
 -- it might be used to call an internal function from an SQL command.
--- As of 7.3 this query should find internal_in, and as of 9.6 aggregate
--- deserialization will be found too. These should contain a runtime check to
--- ensure they can only be called in an aggregate context.
+-- As of 7.3 this query should find only internal_in.
 
 SELECT p1.oid, p1.proname
 FROM pg_proc as p1
