From cc9b97e3c742bbc0781eb48aff3b055820e04305 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Mon, 28 Aug 2017 14:57:39 +0900
Subject: [PATCH 2/2] Improve overflow checks of pqAddTuple() in libpq

When adding a tuple to an existing PQresult, libpq has been lacking
with checks on the maximum number of tuples it can assign within it.
First, it has forgotten the case where the number of tuples allocated
to a result reaches INT_MAX, in which case things would crash.
Secondly, the size allocated when increasing the room for of tuple
pointers could overflow, so add a sanity check on that.

Per original complain from Igor Korot, which led to a patch suggested
by Tom Lane, written by Michael Paquier.

Discussion: http://postgr.es/m/CA+FnnTxyLWyjY1goewmJNxC==HQCCF4fKkoCTa9qR36oRAHDPw@mail.gmail.com
---
 src/interfaces/libpq/fe-exec.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 10961e679b..797335742f 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -904,6 +904,31 @@ pqAddTuple(PGresult *res, PGresAttValue *tup, const char **errmsgp)
 		int			newSize = (res->tupArrSize > 0) ? res->tupArrSize * 2 : 128;
 		PGresAttValue **newTuples;
 
+		/*
+		 * Do not let the array size grow higher than INT_MAX. If the new
+		 * size estimated is overflowing for the first time, enforce the
+		 * size to its maximum possible. If the maximum is already reached
+		 * when arriving at this point, just fail, there is nothing more to
+		 * do.
+		 */
+		if (res->tupArrSize == INT_MAX)
+		{
+			*errmsgp = libpq_gettext("already too many tuples for row addition");
+			return FALSE;
+		}
+		if (newSize < 0)
+			newSize = INT_MAX;
+
+		/*
+		 * This is more a safe-keeper particularly on 32-bit platforms where
+		 * things could overflow.
+		 */
+		if (newSize > SIZE_MAX / sizeof(PGresAttValue *))
+		{
+			*errmsgp = libpq_gettext("size overflow");
+			return FALSE;
+		}
+
 		if (res->tuples == NULL)
 			newTuples = (PGresAttValue **)
 				malloc(newSize * sizeof(PGresAttValue *));
-- 
2.14.1

