CVE-2014-0064: Numeric Errors (CWE-189)
value: Multiple integer overflows in the path_in and other unspecified functions in PostgreSQL before 8.4.20, 9.0.x before 9.0.16, 9.1.x before 9.1.12, 9.2.x before 9.2.7, and 9.3.x before 9.3.3 allow remote authenticated users to have unspecified impact and attack vectors, which trigger a buffer overflow.  NOTE: this identifier has been SPLIT due to different affected versions; use CVE-2014-2669 for the hstore vector.
CWE description: Weaknesses in this category are related to improper calculation or conversion of numbers.
Published: 2014-03-31T14:58Z
Repository: https://github.com/postgres/postgres
Language: C
Files changed: contrib/hstore/hstore.h, contrib/hstore/hstore_io.c, contrib/hstore/hstore_op.c, contrib/intarray/_int.h, contrib/intarray/_int_bool.c, contrib/ltree/ltree.h, contrib/ltree/ltree_io.c, contrib/ltree/ltxtquery_io.c, src/backend/utils/adt/geo_ops.c, src/backend/utils/adt/tsquery.c, src/backend/utils/adt/tsquery_util.c, src/backend/utils/adt/txid.c, src/backend/utils/adt/varbit.c, src/include/tsearch/ts_type.h, src/include/utils/varbit.h
Commit date: 2014-02-17 09:33:31 -0500
Commit message: Predict integer overflow to avoid buffer overruns.

Several functions, mostly type input functions, calculated an allocation
size such that the calculation wrapped to a small positive value when
arguments implied a sufficiently-large requirement.  Writes past the end
of the inadvertent small allocation followed shortly thereafter.
Coverity identified the path_in() vulnerability; code inspection led to
the rest.  In passing, add check_stack_depth() to prevent stack overflow
in related functions.

Back-patch to 8.4 (all supported versions).  The non-comment hstore
changes touch code that did not exist in 8.4, so that part stops at 9.0.

Noah Misch and Heikki Linnakangas, reviewed by Tom Lane.

Security: CVE-2014-0064

Diff: diff --git a/contrib/hstore/hstore.h b/contrib/hstore/hstore.h
index 23c8a6f0e2..37e4611853 100644
--- a/contrib/hstore/hstore.h
+++ b/contrib/hstore/hstore.h
@@ -47,20 +47,29 @@ typedef struct
 	uint32		size_;			/* flags and number of items in hstore */
 	/* array of HEntry follows */
 } HStore;
 
 /*
- * it's not possible to get more than 2^28 items into an hstore,
- * so we reserve the top few bits of the size field. See hstore_compat.c
- * for one reason why.	Some bits are left for future use here.
+ * It's not possible to get more than 2^28 items into an hstore, so we reserve
+ * the top few bits of the size field.  See hstore_compat.c for one reason
+ * why.  Some bits are left for future use here.  MaxAllocSize makes the
+ * practical count limit slightly more than 2^28 / 3, or INT_MAX / 24, the
+ * limit for an hstore full of 4-byte keys and null values.  Therefore, we
+ * don't explicitly check the format-imposed limit.
  */
 #define HS_FLAG_NEWVERSION 0x80000000
 
 #define HS_COUNT(hsp_) ((hsp_)->size_ & 0x0FFFFFFF)
 #define HS_SETCOUNT(hsp_,c_) ((hsp_)->size_ = (c_) | HS_FLAG_NEWVERSION)
 
 
+/*
+ * "x" comes from an existing HS_COUNT() (as discussed, <= INT_MAX/24) or a
+ * Pairs array length (due to MaxAllocSize, <= INT_MAX/40).  "lenstr" is no
+ * more than INT_MAX, that extreme case arising in hstore_from_arrays().
+ * Therefore, this calculation is limited to about INT_MAX / 5 + INT_MAX.
+ */
 #define HSHRDSIZE	(sizeof(HStore))
 #define CALCDATASIZE(x, lenstr) ( (x) * 2 * sizeof(HEntry) + HSHRDSIZE + (lenstr) )
 
 /* note multiple evaluations of x */
 #define ARRPTR(x)		( (HEntry*) ( (HStore*)(x) + 1 ) )
diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c
index 973a1265c1..6dd3f7c24e 100644
--- a/contrib/hstore/hstore_io.c
+++ b/contrib/hstore/hstore_io.c
@@ -11,10 +11,11 @@
 #include "lib/stringinfo.h"
 #include "libpq/pqformat.h"
 #include "utils/builtins.h"
 #include "utils/json.h"
 #include "utils/lsyscache.h"
+#include "utils/memutils.h"
 #include "utils/typcache.h"
 
 #include "hstore.h"
 
 PG_MODULE_MAGIC;
@@ -437,10 +438,15 @@ hstore_recv(PG_FUNCTION_ARGS)
 	{
 		out = hstorePairs(NULL, 0, 0);
 		PG_RETURN_POINTER(out);
 	}
 
+	if (pcount < 0 || pcount > MaxAllocSize / sizeof(Pairs))
+		ereport(ERROR,
+				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+			  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
+					 pcount, (int) (MaxAllocSize / sizeof(Pairs)))));
 	pairs = palloc(pcount * sizeof(Pairs));
 
 	for (i = 0; i < pcount; ++i)
 	{
 		int			rawlen = pq_getmsgint(buf, 4);
@@ -552,10 +558,17 @@ hstore_from_arrays(PG_FUNCTION_ARGS)
 
 	deconstruct_array(key_array,
 					  TEXTOID, -1, false, 'i',
 					  &key_datums, &key_nulls, &key_count);
 
+	/* see discussion in hstoreArrayToPairs() */
+	if (key_count > MaxAllocSize / sizeof(Pairs))
+		ereport(ERROR,
+				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+			  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
+					 key_count, (int) (MaxAllocSize / sizeof(Pairs)))));
+
 	/* value_array might be NULL */
 
 	if (PG_ARGISNULL(1))
 	{
 		value_array = NULL;
@@ -674,10 +687,17 @@ hstore_from_array(PG_FUNCTION_ARGS)
 					  TEXTOID, -1, false, 'i',
 					  &in_datums, &in_nulls, &in_count);
 
 	count = in_count / 2;
 
+	/* see discussion in hstoreArrayToPairs() */
+	if (count > MaxAllocSize / sizeof(Pairs))
+		ereport(ERROR,
+				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+			  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
+					 count, (int) (MaxAllocSize / sizeof(Pairs)))));
+
 	pairs = palloc(count * sizeof(Pairs));
 
 	for (i = 0; i < count; ++i)
 	{
 		if (in_nulls[i * 2])
@@ -805,10 +825,11 @@ hstore_from_record(PG_FUNCTION_ARGS)
 		my_extra->record_type = tupType;
 		my_extra->record_typmod = tupTypmod;
 		my_extra->ncolumns = ncolumns;
 	}
 
+	Assert(ncolumns <= MaxTupleAttributeNumber);		/* thus, no overflow */
 	pairs = palloc(ncolumns * sizeof(Pairs));
 
 	if (rec)
 	{
 		/* Build a temporary HeapTuple control structure */
diff --git a/contrib/hstore/hstore_op.c b/contrib/hstore/hstore_op.c
index 45edb048ce..8ba7a05a65 100644
--- a/contrib/hstore/hstore_op.c
+++ b/contrib/hstore/hstore_op.c
@@ -6,10 +6,11 @@
 #include "access/hash.h"
 #include "access/htup_details.h"
 #include "catalog/pg_type.h"
 #include "funcapi.h"
 #include "utils/builtins.h"
+#include "utils/memutils.h"
 
 #include "hstore.h"
 
 /* old names for C functions */
 HSTORE_POLLUTE(hstore_fetchval, fetchval);
@@ -88,10 +89,23 @@ hstoreArrayToPairs(ArrayType *a, int *npairs)
 	{
 		*npairs = 0;
 		return NULL;
 	}
 
+	/*
+	 * A text array uses at least eight bytes per element, so any overflow in
+	 * "key_count * sizeof(Pairs)" is small enough for palloc() to catch.
+	 * However, credible improvements to the array format could invalidate
+	 * that assumption.  Therefore, use an explicit check rather than relying
+	 * on palloc() to complain.
+	 */
+	if (key_count > MaxAllocSize / sizeof(Pairs))
+		ereport(ERROR,
+				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+			  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
+					 key_count, (int) (MaxAllocSize / sizeof(Pairs)))));
+
 	key_pairs = palloc(sizeof(Pairs) * key_count);
 
 	for (i = 0, j = 0; i < key_count; i++)
 	{
 		if (!key_nulls[i])
@@ -646,10 +660,11 @@ hstore_slice_to_hstore(PG_FUNCTION_ARGS)
 	{
 		out = hstorePairs(NULL, 0, 0);
 		PG_RETURN_POINTER(out);
 	}
 
+	/* hstoreArrayToPairs() checked overflow */
 	out_pairs = palloc(sizeof(Pairs) * nkeys);
 	bufsiz = 0;
 
 	/*
 	 * we exploit the fact that the pairs list is already sorted into strictly
diff --git a/contrib/intarray/_int.h b/contrib/intarray/_int.h
index 56aa23cfde..7f93206e89 100644
--- a/contrib/intarray/_int.h
+++ b/contrib/intarray/_int.h
@@ -3,10 +3,11 @@
  */
 #ifndef ___INT_H__
 #define ___INT_H__
 
 #include "utils/array.h"
+#include "utils/memutils.h"
 
 /* number ranges for compression */
 #define MAXNUMRANGE 100
 
 /* useful macros for accessing int4 arrays */
@@ -135,10 +136,11 @@ typedef struct QUERYTYPE
 	ITEM		items[1];		/* variable length array */
 } QUERYTYPE;
 
 #define HDRSIZEQT	offsetof(QUERYTYPE, items)
 #define COMPUTESIZE(size)	( HDRSIZEQT + (size) * sizeof(ITEM) )
+#define QUERYTYPEMAXITEMS	((MaxAllocSize - HDRSIZEQT) / sizeof(ITEM))
 #define GETQUERY(x)  ( (x)->items )
 
 /* "type" codes for ITEM */
 #define END		0
 #define ERR		1
diff --git a/contrib/intarray/_int_bool.c b/contrib/intarray/_int_bool.c
index d0572afc1e..b18e997748 100644
--- a/contrib/intarray/_int_bool.c
+++ b/contrib/intarray/_int_bool.c
@@ -446,10 +446,13 @@ boolop(PG_FUNCTION_ARGS)
 }
 
 static void
 findoprnd(ITEM *ptr, int32 *pos)
 {
+	/* since this function recurses, it could be driven to stack overflow. */
+	check_stack_depth();
+
 #ifdef BS_DEBUG
 	elog(DEBUG3, (ptr[*pos].type == OPR) ?
 		 "%d  %c" : "%d  %d", *pos, ptr[*pos].val);
 #endif
 	if (ptr[*pos].type == VAL)
@@ -506,11 +509,17 @@ bqarr_in(PG_FUNCTION_ARGS)
 	if (!state.num)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("empty query")));
 
+	if (state.num > QUERYTYPEMAXITEMS)
+		ereport(ERROR,
+				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+		errmsg("number of query items (%d) exceeds the maximum allowed (%d)",
+			   state.num, (int) QUERYTYPEMAXITEMS)));
 	commonlen = COMPUTESIZE(state.num);
+
 	query = (QUERYTYPE *) palloc(commonlen);
 	SET_VARSIZE(query, commonlen);
 	query->size = state.num;
 	ptr = GETQUERY(query);
 
diff --git a/contrib/ltree/ltree.h b/contrib/ltree/ltree.h
index 563970a67a..1b1305b483 100644
--- a/contrib/ltree/ltree.h
+++ b/contrib/ltree/ltree.h
@@ -3,10 +3,11 @@
 #ifndef __LTREE_H__
 #define __LTREE_H__
 
 #include "fmgr.h"
 #include "tsearch/ts_locale.h"
+#include "utils/memutils.h"
 
 typedef struct
 {
 	uint16		len;
 	char		name[1];
@@ -109,10 +110,12 @@ typedef struct
 	char		data[1];
 } ltxtquery;
 
 #define HDRSIZEQT		MAXALIGN(VARHDRSZ + sizeof(int32))
 #define COMPUTESIZE(size,lenofoperand)	( HDRSIZEQT + (size) * sizeof(ITEM) + (lenofoperand) )
+#define LTXTQUERY_TOO_BIG(size,lenofoperand) \
+	((size) > (MaxAllocSize - HDRSIZEQT - (lenofoperand)) / sizeof(ITEM))
 #define GETQUERY(x)  (ITEM*)( (char*)(x)+HDRSIZEQT )
 #define GETOPERAND(x)	( (char*)GETQUERY(x) + ((ltxtquery*)x)->size * sizeof(ITEM) )
 
 #define ISOPERATOR(x) ( (x)=='!' || (x)=='&' || (x)=='|' || (x)=='(' || (x)==')' )
 
diff --git a/contrib/ltree/ltree_io.c b/contrib/ltree/ltree_io.c
index 3e88b81c16..d64debb5f4 100644
--- a/contrib/ltree/ltree_io.c
+++ b/contrib/ltree/ltree_io.c
@@ -6,10 +6,11 @@
 #include "postgres.h"
 
 #include <ctype.h>
 
 #include "ltree.h"
+#include "utils/memutils.h"
 #include "crc32.h"
 
 PG_FUNCTION_INFO_V1(ltree_in);
 Datum		ltree_in(PG_FUNCTION_ARGS);
 
@@ -62,10 +63,15 @@ ltree_in(PG_FUNCTION_ARGS)
 		if (charlen == 1 && t_iseq(ptr, '.'))
 			num++;
 		ptr += charlen;
 	}
 
+	if (num + 1 > MaxAllocSize / sizeof(nodeitem))
+		ereport(ERROR,
+				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+			 errmsg("number of levels (%d) exceeds the maximum allowed (%d)",
+					num + 1, (int) (MaxAllocSize / sizeof(nodeitem)))));
 	list = lptr = (nodeitem *) palloc(sizeof(nodeitem) * (num + 1));
 	ptr = buf;
 	while (*ptr)
 	{
 		charlen = pg_mblen(ptr);
@@ -226,10 +232,15 @@ lquery_in(PG_FUNCTION_ARGS)
 
 		ptr += charlen;
 	}
 
 	num++;
+	if (num > MaxAllocSize / ITEMSIZE)
+		ereport(ERROR,
+				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+			 errmsg("number of levels (%d) exceeds the maximum allowed (%d)",
+					num, (int) (MaxAllocSize / ITEMSIZE))));
 	curqlevel = tmpql = (lquery_level *) palloc0(ITEMSIZE * num);
 	ptr = buf;
 	while (*ptr)
 	{
 		charlen = pg_mblen(ptr);
diff --git a/contrib/ltree/ltxtquery_io.c b/contrib/ltree/ltxtquery_io.c
index 583ff2aaeb..982186581a 100644
--- a/contrib/ltree/ltxtquery_io.c
+++ b/contrib/ltree/ltxtquery_io.c
@@ -7,10 +7,11 @@
 
 #include <ctype.h>
 
 #include "crc32.h"
 #include "ltree.h"
+#include "miscadmin.h"
 
 PG_FUNCTION_INFO_V1(ltxtq_in);
 Datum		ltxtq_in(PG_FUNCTION_ARGS);
 
 PG_FUNCTION_INFO_V1(ltxtq_out);
@@ -210,10 +211,13 @@ makepol(QPRS_STATE *state)
 	char	   *strval = NULL;
 	int32		stack[STACKDEPTH];
 	int32		lenstack = 0;
 	uint16		flag = 0;
 
+	/* since this function recurses, it could be driven to stack overflow */
+	check_stack_depth();
+
 	while ((type = gettoken_query(state, &val, &lenval, &strval, &flag)) != END)
 	{
 		switch (type)
 		{
 			case VAL:
@@ -274,10 +278,13 @@ makepol(QPRS_STATE *state)
 }
 
 static void
 findoprnd(ITEM *ptr, int32 *pos)
 {
+	/* since this function recurses, it could be driven to stack overflow. */
+	check_stack_depth();
+
 	if (ptr[*pos].type == VAL || ptr[*pos].type == VALTRUE)
 	{
 		ptr[*pos].left = 0;
 		(*pos)++;
 	}
@@ -338,12 +345,16 @@ queryin(char *buf)
 		ereport(ERROR,
 				(errcode(ERRCODE_SYNTAX_ERROR),
 				 errmsg("syntax error"),
 				 errdetail("Empty query.")));
 
-	/* make finish struct */
+	if (LTXTQUERY_TOO_BIG(state.num, state.sumlen))
+		ereport(ERROR,
+				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+				 errmsg("ltxtquery is too large")));
 	commonlen = COMPUTESIZE(state.num, state.sumlen);
+
 	query = (ltxtquery *) palloc(commonlen);
 	SET_VARSIZE(query, commonlen);
 	query->size = state.num;
 	ptr = GETQUERY(query);
 
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 0a68be66ef..f267920649 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -1364,10 +1364,11 @@ path_in(PG_FUNCTION_ARGS)
 	PATH	   *path;
 	int			isopen;
 	char	   *s;
 	int			npts;
 	int			size;
+	int			base_size;
 	int			depth = 0;
 
 	if ((npts = pair_count(str, ',')) <= 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
@@ -1382,11 +1383,19 @@ path_in(PG_FUNCTION_ARGS)
 	{
 		s++;
 		depth++;
 	}
 
-	size = offsetof(PATH, p[0]) +sizeof(path->p[0]) * npts;
+	base_size = sizeof(path->p[0]) * npts;
+	size = offsetof(PATH, p[0]) + base_size;
+
+	/* Check for integer overflow */
+	if (base_size / npts != sizeof(path->p[0]) || size <= base_size)
+		ereport(ERROR,
+				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+				 errmsg("too many points requested")));
+
 	path = (PATH *) palloc(size);
 
 	SET_VARSIZE(path, size);
 	path->npts = npts;
 
@@ -3427,19 +3436,28 @@ poly_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
 	POLYGON    *poly;
 	int			npts;
 	int			size;
+	int			base_size;
 	int			isopen;
 	char	   *s;
 
 	if ((npts = pair_count(str, ',')) <= 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 			  errmsg("invalid input syntax for type polygon: \"%s\"", str)));
 
-	size = offsetof(POLYGON, p[0]) +sizeof(poly->p[0]) * npts;
+	base_size = sizeof(poly->p[0]) * npts;
+	size = offsetof(POLYGON, p[0]) + base_size;
+
+	/* Check for integer overflow */
+	if (base_size / npts != sizeof(poly->p[0]) || size <= base_size)
+		ereport(ERROR,
+				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+				 errmsg("too many points requested")));
+
 	poly = (POLYGON *) palloc0(size);	/* zero any holes */
 
 	SET_VARSIZE(poly, size);
 	poly->npts = npts;
 
@@ -4341,10 +4359,14 @@ path_poly(PG_FUNCTION_ARGS)
 	if (!path->closed)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("open path cannot be converted to polygon")));
 
+	/*
+	 * Never overflows: the old size fit in MaxAllocSize, and the new size is
+	 * just a small constant larger.
+	 */
 	size = offsetof(POLYGON, p[0]) +sizeof(poly->p[0]) * path->npts;
 	poly = (POLYGON *) palloc(size);
 
 	SET_VARSIZE(poly, size);
 	poly->npts = path->npts;
@@ -4446,10 +4468,14 @@ poly_path(PG_FUNCTION_ARGS)
 	POLYGON    *poly = PG_GETARG_POLYGON_P(0);
 	PATH	   *path;
 	int			size;
 	int			i;
 
+	/*
+	 * Never overflows: the old size fit in MaxAllocSize, and the new size is
+	 * smaller by a small constant.
+	 */
 	size = offsetof(PATH, p[0]) +sizeof(path->p[0]) * poly->npts;
 	path = (PATH *) palloc(size);
 
 	SET_VARSIZE(path, size);
 	path->npts = poly->npts;
diff --git a/src/backend/utils/adt/tsquery.c b/src/backend/utils/adt/tsquery.c
index 90ca37b0f7..b973a534dd 100644
--- a/src/backend/utils/adt/tsquery.c
+++ b/src/backend/utils/adt/tsquery.c
@@ -512,12 +512,17 @@ parse_tsquery(char *buf,
 		SET_VARSIZE(query, HDRSIZETQ);
 		query->size = 0;
 		return query;
 	}
 
-	/* Pack the QueryItems in the final TSQuery struct to return to caller */
+	if (TSQUERY_TOO_BIG(list_length(state.polstr), state.sumlen))
+		ereport(ERROR,
+				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+				 errmsg("tsquery is too large")));
 	commonlen = COMPUTESIZE(list_length(state.polstr), state.sumlen);
+
+	/* Pack the QueryItems in the final TSQuery struct to return to caller */
 	query = (TSQuery) palloc0(commonlen);
 	SET_VARSIZE(query, commonlen);
 	query->size = list_length(state.polstr);
 	ptr = GETQUERY(query);
 
diff --git a/src/backend/utils/adt/tsquery_util.c b/src/backend/utils/adt/tsquery_util.c
index 34587980c7..8a41fbc531 100644
--- a/src/backend/utils/adt/tsquery_util.c
+++ b/src/backend/utils/adt/tsquery_util.c
@@ -331,10 +331,15 @@ QTN2QT(QTNode *in)
 	int			sumlen = 0,
 				nnode = 0;
 	QTN2QTState state;
 
 	cntsize(in, &sumlen, &nnode);
+
+	if (TSQUERY_TOO_BIG(nnode, sumlen))
+		ereport(ERROR,
+				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+				 errmsg("tsquery is too large")));
 	len = COMPUTESIZE(nnode, sumlen);
 
 	out = (TSQuery) palloc0(len);
 	SET_VARSIZE(out, len);
 	out->size = nnode;
diff --git a/src/backend/utils/adt/txid.c b/src/backend/utils/adt/txid.c
index 56d599f07d..a005e676b5 100644
--- a/src/backend/utils/adt/txid.c
+++ b/src/backend/utils/adt/txid.c
@@ -24,11 +24,13 @@
 #include "access/transam.h"
 #include "access/xact.h"
 #include "funcapi.h"
 #include "miscadmin.h"
 #include "libpq/pqformat.h"
+#include "postmaster/postmaster.h"
 #include "utils/builtins.h"
+#include "utils/memutils.h"
 #include "utils/snapmgr.h"
 
 
 /* txid will be signed int8 in database, so must limit to 63 bits */
 #define MAX_TXID   UINT64CONST(0x7FFFFFFFFFFFFFFF)
@@ -64,10 +66,12 @@ typedef struct
 	txid		xip[1];			/* in-progress txids, xmin <= xip[i] < xmax */
 } TxidSnapshot;
 
 #define TXID_SNAPSHOT_SIZE(nxip) \
 	(offsetof(TxidSnapshot, xip) + sizeof(txid) * (nxip))
+#define TXID_SNAPSHOT_MAX_NXIP \
+	((MaxAllocSize - offsetof(TxidSnapshot, xip)) / sizeof(txid))
 
 /*
  * Epoch values from xact.c
  */
 typedef struct
@@ -366,10 +370,17 @@ txid_current_snapshot(PG_FUNCTION_ARGS)
 	if (cur == NULL)
 		elog(ERROR, "no active snapshot set");
 
 	load_xid_epoch(&state);
 
+	/*
+	 * Compile-time limits on the procarray (MAX_BACKENDS processes plus
+	 * MAX_BACKENDS prepared transactions) guarantee nxip won't be too large.
+	 */
+	StaticAssertStmt(MAX_BACKENDS * 2 <= TXID_SNAPSHOT_MAX_NXIP,
+					 "possible overflow in txid_current_snapshot()");
+
 	/* allocate */
 	nxip = cur->xcnt;
 	size = TXID_SNAPSHOT_SIZE(nxip);
 	snap = palloc(size);
 	SET_VARSIZE(snap, size);
@@ -443,24 +454,16 @@ txid_snapshot_recv(PG_FUNCTION_ARGS)
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	TxidSnapshot *snap;
 	txid		last = 0;
 	int			nxip;
 	int			i;
-	int			avail;
-	int			expect;
 	txid		xmin,
 				xmax;
 
-	/*
-	 * load nxip and check for nonsense.
-	 *
-	 * (nxip > avail) check is against int overflows in 'expect'.
-	 */
+	/* load and validate nxip */
 	nxip = pq_getmsgint(buf, 4);
-	avail = buf->len - buf->cursor;
-	expect = 8 + 8 + nxip * 8;
-	if (nxip < 0 || nxip > avail || expect > avail)
+	if (nxip < 0 || nxip > TXID_SNAPSHOT_MAX_NXIP)
 		goto bad_format;
 
 	xmin = pq_getmsgint64(buf);
 	xmax = pq_getmsgint64(buf);
 	if (xmin == 0 || xmax == 0 || xmin > xmax || xmax > MAX_TXID)
diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c
index 22c04be307..e3de952863 100644
--- a/src/backend/utils/adt/varbit.c
+++ b/src/backend/utils/adt/varbit.c
@@ -146,16 +146,26 @@ bit_in(PG_FUNCTION_ARGS)
 		 */
 		bit_not_hex = true;
 		sp = input_string;
 	}
 
+	/*
+	 * Determine bitlength from input string.  MaxAllocSize ensures a regular
+	 * input is small enough, but we must check hex input.
+	 */
 	slen = strlen(sp);
-	/* Determine bitlength from input string */
 	if (bit_not_hex)
 		bitlen = slen;
 	else
+	{
+		if (slen > VARBITMAXLEN / 4)
+			ereport(ERROR,
+					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+				 errmsg("bit string length exceeds the maximum allowed (%d)",
+						VARBITMAXLEN)));
 		bitlen = slen * 4;
+	}
 
 	/*
 	 * Sometimes atttypmod is not supplied. If it is supplied we need to make
 	 * sure that the bitstring fits.
 	 */
@@ -448,16 +458,26 @@ varbit_in(PG_FUNCTION_ARGS)
 	{
 		bit_not_hex = true;
 		sp = input_string;
 	}
 
+	/*
+	 * Determine bitlength from input string.  MaxAllocSize ensures a regular
+	 * input is small enough, but we must check hex input.
+	 */
 	slen = strlen(sp);
-	/* Determine bitlength from input string */
 	if (bit_not_hex)
 		bitlen = slen;
 	else
+	{
+		if (slen > VARBITMAXLEN / 4)
+			ereport(ERROR,
+					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+				 errmsg("bit string length exceeds the maximum allowed (%d)",
+						VARBITMAXLEN)));
 		bitlen = slen * 4;
+	}
 
 	/*
 	 * Sometimes atttypmod is not supplied. If it is supplied we need to make
 	 * sure that the bitstring fits.
 	 */
@@ -533,10 +553,13 @@ varbit_in(PG_FUNCTION_ARGS)
 }
 
 /*
  * varbit_out -
  *	  Prints the string as bits to preserve length accurately
+ *
+ * XXX varbit_recv() and hex input to varbit_in() can load a value that this
+ * cannot emit.  Consider using hex output for such values.
  */
 Datum
 varbit_out(PG_FUNCTION_ARGS)
 {
 	VarBit	   *s = PG_GETARG_VARBIT_P(0);
@@ -942,10 +965,15 @@ bit_catenate(VarBit *arg1, VarBit *arg2)
 			   *pa;
 
 	bitlen1 = VARBITLEN(arg1);
 	bitlen2 = VARBITLEN(arg2);
 
+	if (bitlen1 > VARBITMAXLEN - bitlen2)
+		ereport(ERROR,
+				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+				 errmsg("bit string length exceeds the maximum allowed (%d)",
+						VARBITMAXLEN)));
 	bytelen = VARBITTOTALLEN(bitlen1 + bitlen2);
 
 	result = (VarBit *) palloc(bytelen);
 	SET_VARSIZE(result, bytelen);
 	VARBITLEN(result) = bitlen1 + bitlen2;
diff --git a/src/include/tsearch/ts_type.h b/src/include/tsearch/ts_type.h
index 4e253fb9d3..df4a57825e 100644
--- a/src/include/tsearch/ts_type.h
+++ b/src/include/tsearch/ts_type.h
@@ -11,10 +11,11 @@
  */
 #ifndef _PG_TSTYPE_H_
 #define _PG_TSTYPE_H_
 
 #include "fmgr.h"
+#include "utils/memutils.h"
 #include "utils/pg_crc.h"
 
 
 /*
  * TSVector type.
@@ -242,10 +243,12 @@ typedef TSQueryData *TSQuery;
 
 /* Computes the size of header and all QueryItems. size is the number of
  * QueryItems, and lenofoperand is the total length of all operands
  */
 #define COMPUTESIZE(size, lenofoperand) ( HDRSIZETQ + (size) * sizeof(QueryItem) + (lenofoperand) )
+#define TSQUERY_TOO_BIG(size, lenofoperand) \
+	((size) > (MaxAllocSize - HDRSIZETQ - (lenofoperand)) / sizeof(QueryItem))
 
 /* Returns a pointer to the first QueryItem in a TSQuery */
 #define GETQUERY(x)  ((QueryItem*)( (char*)(x)+HDRSIZETQ ))
 
 /* Returns a pointer to the beginning of operands in a TSQuery */
diff --git a/src/include/utils/varbit.h b/src/include/utils/varbit.h
index 773b4ce050..974de7db09 100644
--- a/src/include/utils/varbit.h
+++ b/src/include/utils/varbit.h
@@ -13,10 +13,12 @@
  *-------------------------------------------------------------------------
  */
 #ifndef VARBIT_H
 #define VARBIT_H
 
+#include <limits.h>
+
 #include "fmgr.h"
 
 /*
  * Modeled on struct varlena from postgres.h, but data type is bits8.
  */
@@ -51,10 +53,15 @@ typedef struct
 /* Padding of the bit string at the end (in bits) */
 #define VARBITPAD(PTR)		(VARBITBYTES(PTR)*BITS_PER_BYTE - VARBITLEN(PTR))
 /* Number of bytes needed to store a bit string of a given length */
 #define VARBITTOTALLEN(BITLEN)	(((BITLEN) + BITS_PER_BYTE-1)/BITS_PER_BYTE + \
 								 VARHDRSZ + VARBITHDRSZ)
+/*
+ * Maximum number of bits.  Several code sites assume no overflow from
+ * computing bitlen + X; VARBITTOTALLEN() has the largest such X.
+ */
+#define VARBITMAXLEN		(INT_MAX - BITS_PER_BYTE + 1)
 /* pointer beyond the end of the bit string (like end() in STL containers) */
 #define VARBITEND(PTR)		(((bits8 *) (PTR)) + VARSIZE(PTR))
 /* Mask that will cover exactly one byte, i.e. BITS_PER_BYTE bits */
 #define BITMASK 0xFF
 

Vulnerable code:  * it's not possible to get more than 2^28 items into an hstore,
 * so we reserve the top few bits of the size field. See hstore_compat.c
 * for one reason why.	Some bits are left for future use here.
	/* make finish struct */
	size = offsetof(PATH, p[0]) +sizeof(path->p[0]) * npts;
	size = offsetof(POLYGON, p[0]) +sizeof(poly->p[0]) * npts;
	/* Pack the QueryItems in the final TSQuery struct to return to caller */
	int			avail;
	int			expect;
	/*
	 * load nxip and check for nonsense.
	 *
	 * (nxip > avail) check is against int overflows in 'expect'.
	 */
	avail = buf->len - buf->cursor;
	expect = 8 + 8 + nxip * 8;
	if (nxip < 0 || nxip > avail || expect > avail)
	/* Determine bitlength from input string */
	/* Determine bitlength from input string */
Fixed code:  * It's not possible to get more than 2^28 items into an hstore, so we reserve
 * the top few bits of the size field.  See hstore_compat.c for one reason
 * why.  Some bits are left for future use here.  MaxAllocSize makes the
 * practical count limit slightly more than 2^28 / 3, or INT_MAX / 24, the
 * limit for an hstore full of 4-byte keys and null values.  Therefore, we
 * don't explicitly check the format-imposed limit.
/*
 * "x" comes from an existing HS_COUNT() (as discussed, <= INT_MAX/24) or a
 * Pairs array length (due to MaxAllocSize, <= INT_MAX/40).  "lenstr" is no
 * more than INT_MAX, that extreme case arising in hstore_from_arrays().
 * Therefore, this calculation is limited to about INT_MAX / 5 + INT_MAX.
 */
#include "utils/memutils.h"
	if (pcount < 0 || pcount > MaxAllocSize / sizeof(Pairs))
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
			  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
					 pcount, (int) (MaxAllocSize / sizeof(Pairs)))));
	/* see discussion in hstoreArrayToPairs() */
	if (key_count > MaxAllocSize / sizeof(Pairs))
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
			  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
					 key_count, (int) (MaxAllocSize / sizeof(Pairs)))));

	/* see discussion in hstoreArrayToPairs() */
	if (count > MaxAllocSize / sizeof(Pairs))
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
			  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
					 count, (int) (MaxAllocSize / sizeof(Pairs)))));

	Assert(ncolumns <= MaxTupleAttributeNumber);		/* thus, no overflow */
#include "utils/memutils.h"
	/*
	 * A text array uses at least eight bytes per element, so any overflow in
	 * "key_count * sizeof(Pairs)" is small enough for palloc() to catch.
	 * However, credible improvements to the array format could invalidate
	 * that assumption.  Therefore, use an explicit check rather than relying
	 * on palloc() to complain.
	 */
	if (key_count > MaxAllocSize / sizeof(Pairs))
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
			  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
					 key_count, (int) (MaxAllocSize / sizeof(Pairs)))));

	/* hstoreArrayToPairs() checked overflow */
#include "utils/memutils.h"
#define QUERYTYPEMAXITEMS	((MaxAllocSize - HDRSIZEQT) / sizeof(ITEM))
	/* since this function recurses, it could be driven to stack overflow. */
	check_stack_depth();

	if (state.num > QUERYTYPEMAXITEMS)
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
		errmsg("number of query items (%d) exceeds the maximum allowed (%d)",
			   state.num, (int) QUERYTYPEMAXITEMS)));

#include "utils/memutils.h"
#define LTXTQUERY_TOO_BIG(size,lenofoperand) \
	((size) > (MaxAllocSize - HDRSIZEQT - (lenofoperand)) / sizeof(ITEM))
#include "utils/memutils.h"
	if (num + 1 > MaxAllocSize / sizeof(nodeitem))
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
			 errmsg("number of levels (%d) exceeds the maximum allowed (%d)",
					num + 1, (int) (MaxAllocSize / sizeof(nodeitem)))));
	if (num > MaxAllocSize / ITEMSIZE)
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
			 errmsg("number of levels (%d) exceeds the maximum allowed (%d)",
					num, (int) (MaxAllocSize / ITEMSIZE))));
#include "miscadmin.h"
	/* since this function recurses, it could be driven to stack overflow */
	check_stack_depth();

	/* since this function recurses, it could be driven to stack overflow. */
	check_stack_depth();

	if (LTXTQUERY_TOO_BIG(state.num, state.sumlen))
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
				 errmsg("ltxtquery is too large")));

	int			base_size;
	base_size = sizeof(path->p[0]) * npts;
	size = offsetof(PATH, p[0]) + base_size;

	/* Check for integer overflow */
	if (base_size / npts != sizeof(path->p[0]) || size <= base_size)
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
				 errmsg("too many points requested")));

	int			base_size;
	base_size = sizeof(poly->p[0]) * npts;
	size = offsetof(POLYGON, p[0]) + base_size;

	/* Check for integer overflow */
	if (base_size / npts != sizeof(poly->p[0]) || size <= base_size)
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
				 errmsg("too many points requested")));

	/*
	 * Never overflows: the old size fit in MaxAllocSize, and the new size is
	 * just a small constant larger.
	 */
	/*
	 * Never overflows: the old size fit in MaxAllocSize, and the new size is
	 * smaller by a small constant.
	 */
	if (TSQUERY_TOO_BIG(list_length(state.polstr), state.sumlen))
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
				 errmsg("tsquery is too large")));

	/* Pack the QueryItems in the final TSQuery struct to return to caller */

	if (TSQUERY_TOO_BIG(nnode, sumlen))
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
				 errmsg("tsquery is too large")));
#include "postmaster/postmaster.h"
#include "utils/memutils.h"
#define TXID_SNAPSHOT_MAX_NXIP \
	((MaxAllocSize - offsetof(TxidSnapshot, xip)) / sizeof(txid))
	/*
	 * Compile-time limits on the procarray (MAX_BACKENDS processes plus
	 * MAX_BACKENDS prepared transactions) guarantee nxip won't be too large.
	 */
	StaticAssertStmt(MAX_BACKENDS * 2 <= TXID_SNAPSHOT_MAX_NXIP,
					 "possible overflow in txid_current_snapshot()");

	/* load and validate nxip */
	if (nxip < 0 || nxip > TXID_SNAPSHOT_MAX_NXIP)
	/*
	 * Determine bitlength from input string.  MaxAllocSize ensures a regular
	 * input is small enough, but we must check hex input.
	 */
	{
		if (slen > VARBITMAXLEN / 4)
			ereport(ERROR,
					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
				 errmsg("bit string length exceeds the maximum allowed (%d)",
						VARBITMAXLEN)));
	}
	/*
	 * Determine bitlength from input string.  MaxAllocSize ensures a regular
	 * input is small enough, but we must check hex input.
	 */
	{
		if (slen > VARBITMAXLEN / 4)
			ereport(ERROR,
					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
				 errmsg("bit string length exceeds the maximum allowed (%d)",
						VARBITMAXLEN)));
	}
 *
 * XXX varbit_recv() and hex input to varbit_in() can load a value that this
 * cannot emit.  Consider using hex output for such values.
	if (bitlen1 > VARBITMAXLEN - bitlen2)
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
				 errmsg("bit string length exceeds the maximum allowed (%d)",
						VARBITMAXLEN)));
#include "utils/memutils.h"
#define TSQUERY_TOO_BIG(size, lenofoperand) \
	((size) > (MaxAllocSize - HDRSIZETQ - (lenofoperand)) / sizeof(QueryItem))
#include <limits.h>

/*
 * Maximum number of bits.  Several code sites assume no overflow from
 * computing bitlen + X; VARBITTOTALLEN() has the largest such X.
 */
#define VARBITMAXLEN		(INT_MAX - BITS_PER_BYTE + 1)