aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/txid.c
diff options
context:
space:
mode:
authorNoah Misch <noah@leadboat.com>2014-02-17 09:33:31 -0500
committerNoah Misch <noah@leadboat.com>2014-02-17 09:33:32 -0500
commit7a362a176a5c6621b58fb3897b2a4cb15b975810 (patch)
treeb6c052e2e69fe1424ee0e0868aa609fe2da28ebb /src/backend/utils/adt/txid.c
parente4a4fa22352b062bc3548c91fa9bfc6caed7b073 (diff)
downloadpostgresql-7a362a176a5c6621b58fb3897b2a4cb15b975810.tar.gz
postgresql-7a362a176a5c6621b58fb3897b2a4cb15b975810.zip
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
Diffstat (limited to 'src/backend/utils/adt/txid.c')
-rw-r--r--src/backend/utils/adt/txid.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/src/backend/utils/adt/txid.c b/src/backend/utils/adt/txid.c
index de867561cd1..ac6ea7de33e 100644
--- a/src/backend/utils/adt/txid.c
+++ b/src/backend/utils/adt/txid.c
@@ -26,7 +26,9 @@
#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"
@@ -66,6 +68,8 @@ typedef struct
#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
@@ -368,6 +372,13 @@ txid_current_snapshot(PG_FUNCTION_ARGS)
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);
@@ -445,20 +456,12 @@ txid_snapshot_recv(PG_FUNCTION_ARGS)
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);