From 2fc80b9ae6000ccf9223812b9149375abf0ee579 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 13 Feb 2006 22:33:57 +0000
Subject: [PATCH] Add positive defense against trying to connect when the
 connection option state hasn't been fully set up.  This is possible via
 PQreset() and might occur in other code paths too, so a state flag seems the
 most robust solution.  Per report from Arturs Zoldners.

---
 src/interfaces/libpq/fe-connect.c | 15 +++++++++++++--
 src/interfaces/libpq/libpq-int.h  |  6 +++---
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 69db8d830cb..db7549f2bcf 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.325 2006/01/11 08:43:13 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.326 2006/02/13 22:33:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -505,6 +505,13 @@ connectOptions2(PGconn *conn)
 	else
 		conn->sslmode = strdup(DefaultSSLMode);
 
+	/*
+	 * Only if we get this far is it appropriate to try to connect.
+	 * (We need a state flag, rather than just the boolean result of
+	 * this function, in case someone tries to PQreset() the PGconn.)
+	 */
+	conn->options_valid = true;
+
 	return true;
 }
 
@@ -729,6 +736,9 @@ connectDBStart(PGconn *conn)
 	if (!conn)
 		return 0;
 
+	if (!conn->options_valid)
+		goto connect_errReturn;
+
 	/* Ensure our buffers are empty */
 	conn->inStart = conn->inCursor = conn->inEnd = 0;
 	conn->outCount = 0;
@@ -1814,6 +1824,8 @@ makeEmptyPGconn(void)
 	conn->status = CONNECTION_BAD;
 	conn->asyncStatus = PGASYNC_IDLE;
 	conn->xactStatus = PQTRANS_IDLE;
+	conn->options_valid = false;
+	conn->nonblocking = false;
 	conn->setenv_state = SETENV_STATE_IDLE;
 	conn->client_encoding = PG_SQL_ASCII;
 	conn->verbosity = PQERRORS_DEFAULT;
@@ -1838,7 +1850,6 @@ makeEmptyPGconn(void)
 	conn->inBuffer = (char *) malloc(conn->inBufSize);
 	conn->outBufSize = 16 * 1024;
 	conn->outBuffer = (char *) malloc(conn->outBufSize);
-	conn->nonblocking = FALSE;
 	initPQExpBuffer(&conn->errorMessage);
 	initPQExpBuffer(&conn->workBuffer);
 
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 096ee1b7af4..c8a5527a016 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.109 2005/11/22 18:17:33 momjian Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.110 2006/02/13 22:33:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -276,9 +276,9 @@ struct pg_conn
 	/* Status indicators */
 	ConnStatusType status;
 	PGAsyncStatusType asyncStatus;
-	PGTransactionStatusType xactStatus;
-	/* note: xactStatus never changes to ACTIVE */
+	PGTransactionStatusType xactStatus;		/* never changes to ACTIVE */
 	PGQueryClass queryclass;
+	bool		options_valid;	/* true if OK to attempt connection */
 	bool		nonblocking;	/* whether this connection is using nonblock
 								 * sending semantics */
 	char		copy_is_binary; /* 1 = copy binary, 0 = copy text */
-- 
GitLab