CVE-2014-0064 (C, published 2014-03-31T14:58Z)
Description: 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.
Severity: MEDIUM (CVSS v3 base score: )
Weakness: CWE-189 \u2014 Numeric Errors
Weaknesses in this category are related to improper calculation or conversion of numbers.
Repository: https://github.com/postgres/postgres
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 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


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)