From 539c5d9f767160c774d7dc31b7c57edf7ba7318f Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 8 Feb 2026 15:05:03 +0000 Subject: [PATCH] Fix GH-21162: pg_connect() on error memory leak. The PHP_PQ_ERROR macro calls php_error_docref() which triggers user error handlers thus libpq does not have the chance to clean the resources (and empty connections string are allowed) on failure thus we avoid this macro and delay the error handling after. close GH-21165 --- NEWS | 4 ++++ ext/pgsql/pgsql.c | 12 +++++++++--- ext/pgsql/tests/gh21162.phpt | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 ext/pgsql/tests/gh21162.phpt diff --git a/NEWS b/NEWS index 10a3dd00f2f..536eeafbb8b 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,10 @@ PHP NEWS . Fixed bug GH-21055 (connection attribute status typo for GSS negotiation). (lsaos) +- PGSQL: + . Fixed bug GH-21162 (pg_connect() memory leak on error). + (David Carlier) + - Sockets: . Fixed bug GH-21161 (socket_set_option() crash with array 'addr' entry as null). (David Carlier) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 80aacd5443e..99f2e3cf563 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -705,10 +705,12 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) /* create the link */ pgsql = PQconnectdb(connstring); if (pgsql == NULL || PQstatus(pgsql) == CONNECTION_BAD) { - PHP_PQ_ERROR("Unable to connect to PostgreSQL server: %s", pgsql) + zend_string *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql)); if (pgsql) { PQfinish(pgsql); } + php_error_docref(NULL, E_WARNING, "Unable to connect to PostgreSQL server: %s", ZSTR_VAL(msgbuf)); + zend_string_release(msgbuf); goto err; } @@ -789,19 +791,23 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) if (connect_type & PGSQL_CONNECT_ASYNC) { pgsql = PQconnectStart(connstring); if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) { - PHP_PQ_ERROR("Unable to connect to PostgreSQL server: %s", pgsql); + zend_string *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql)); if (pgsql) { PQfinish(pgsql); } + php_error_docref(NULL, E_WARNING, "Unable to connect to PostgreSQL server: %s", ZSTR_VAL(msgbuf)); + zend_string_release(msgbuf); goto err; } } else { pgsql = PQconnectdb(connstring); if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) { - PHP_PQ_ERROR("Unable to connect to PostgreSQL server: %s", pgsql); + zend_string *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql)); if (pgsql) { PQfinish(pgsql); } + php_error_docref(NULL, E_WARNING, "Unable to connect to PostgreSQL server: %s", ZSTR_VAL(msgbuf)); + zend_string_release(msgbuf); goto err; } } diff --git a/ext/pgsql/tests/gh21162.phpt b/ext/pgsql/tests/gh21162.phpt new file mode 100644 index 00000000000..9f40ac1136d --- /dev/null +++ b/ext/pgsql/tests/gh21162.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-21162 (pg_connect() on error memory leak) +--EXTENSIONS-- +pgsql +--FILE-- + +--EXPECT-- +Warning caught +Done