Skip to content

Commit 0953e89

Browse files
authored
Fix pg_fetch_object() when an error occurs in subroutine (#20407)
This is a follow-up of GH-20068
1 parent 877e758 commit 0953e89

File tree

1 file changed

+28
-14
lines changed

1 file changed

+28
-14
lines changed

ext/pgsql/pgsql.c

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1977,8 +1977,9 @@ PHP_FUNCTION(pg_fetch_result)
19771977
}
19781978
/* }}} */
19791979

1980-
/* {{{ void php_pgsql_fetch_hash */
1981-
static void php_pgsql_fetch_hash(zval *return_value, const zval *result, zend_long row, bool row_is_null, zend_long result_type)
1980+
/* Returns true when the return_value was populated with an array,
1981+
* otherwise when an error occurs false is returned, in which case the return_value is NOT initialized */
1982+
static bool php_pgsql_fetch_hash(zval *return_value, const zval *result, zend_long row, bool row_is_null, zend_long result_type)
19821983
{
19831984
PGresult *pgsql_result;
19841985
pgsql_result_handle *pg_result;
@@ -1987,31 +1988,34 @@ static void php_pgsql_fetch_hash(zval *return_value, const zval *result, zend_lo
19871988

19881989
if (!row_is_null && row < 0) {
19891990
zend_argument_value_error(2, "must be greater than or equal to 0");
1990-
RETURN_THROWS();
1991+
return false;
19911992
}
19921993

19931994
if (!(result_type & PGSQL_BOTH)) {
19941995
zend_argument_value_error(3, "must be one of PGSQL_ASSOC, PGSQL_NUM, or PGSQL_BOTH");
1995-
RETURN_THROWS();
1996+
return false;
19961997
}
19971998

19981999
pg_result = Z_PGSQL_RESULT_P(result);
1999-
CHECK_PGSQL_RESULT(pg_result);
2000+
if (UNEXPECTED(pg_result->result == NULL)) {
2001+
zend_throw_error(NULL, "PostgreSQL result has already been closed");
2002+
return false;
2003+
}
20002004
pgsql_result = pg_result->result;
20012005

20022006
if (!row_is_null) {
20032007
if (row >= PQntuples(pgsql_result)) {
20042008
php_error_docref(NULL, E_WARNING, "Unable to jump to row " ZEND_LONG_FMT " on PostgreSQL result index " ZEND_LONG_FMT,
20052009
row, Z_LVAL_P(result));
2006-
RETURN_FALSE;
2010+
return false;
20072011
}
20082012
pgsql_row = (int)row;
20092013
pg_result->row = pgsql_row;
20102014
} else {
20112015
/* If 2nd param is NULL, use internal row counter to access next row */
20122016
pgsql_row = pg_result->row;
20132017
if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
2014-
RETURN_FALSE;
2018+
return false;
20152019
}
20162020
pg_result->row++;
20172021
}
@@ -2042,8 +2046,8 @@ static void php_pgsql_fetch_hash(zval *return_value, const zval *result, zend_lo
20422046
}
20432047
}
20442048
}
2049+
return true;
20452050
}
2046-
/* }}} */
20472051

20482052
/* {{{ Get a row as an enumerated array */
20492053
PHP_FUNCTION(pg_fetch_row)
@@ -2060,7 +2064,10 @@ PHP_FUNCTION(pg_fetch_row)
20602064
Z_PARAM_LONG(result_type)
20612065
ZEND_PARSE_PARAMETERS_END();
20622066

2063-
php_pgsql_fetch_hash(return_value, result, row, row_is_null, result_type);
2067+
if (UNEXPECTED(!php_pgsql_fetch_hash(return_value, result, row, row_is_null, result_type))) {
2068+
/* Either an exception is thrown, or we return false */
2069+
RETURN_FALSE;
2070+
}
20642071
}
20652072
/* }}} */
20662073

@@ -2077,7 +2084,10 @@ PHP_FUNCTION(pg_fetch_assoc)
20772084
Z_PARAM_LONG_OR_NULL(row, row_is_null)
20782085
ZEND_PARSE_PARAMETERS_END();
20792086

2080-
php_pgsql_fetch_hash(return_value, result, row, row_is_null, PGSQL_ASSOC);
2087+
if (UNEXPECTED(!php_pgsql_fetch_hash(return_value, result, row, row_is_null, PGSQL_ASSOC))) {
2088+
/* Either an exception is thrown, or we return false */
2089+
RETURN_FALSE;
2090+
}
20812091
}
20822092
/* }}} */
20832093

@@ -2096,7 +2106,10 @@ PHP_FUNCTION(pg_fetch_array)
20962106
Z_PARAM_LONG(result_type)
20972107
ZEND_PARSE_PARAMETERS_END();
20982108

2099-
php_pgsql_fetch_hash(return_value, result, row, row_is_null, result_type);
2109+
if (UNEXPECTED(!php_pgsql_fetch_hash(return_value, result, row, row_is_null, result_type))) {
2110+
/* Either an exception is thrown, or we return false */
2111+
RETURN_FALSE;
2112+
}
21002113
}
21012114
/* }}} */
21022115

@@ -2129,10 +2142,11 @@ PHP_FUNCTION(pg_fetch_object)
21292142
RETURN_THROWS();
21302143
}
21312144

2132-
/* pg_fetch_object() allowed result_type used to be. 3rd parameter
2133-
must be allowed for compatibility */
21342145
zval dataset;
2135-
php_pgsql_fetch_hash(&dataset, result, row, row_is_null, PGSQL_ASSOC);
2146+
if (UNEXPECTED(!php_pgsql_fetch_hash(&dataset, result, row, row_is_null, PGSQL_ASSOC))) {
2147+
/* Either an exception is thrown, or we return false */
2148+
RETURN_FALSE;
2149+
}
21362150

21372151
// TODO: Check CE is an instantiable class earlier?
21382152
zend_result obj_initialized = object_init_ex(return_value, ce);

0 commit comments

Comments
 (0)