Skip to content

Commit 81404a2

Browse files
committed
Fix pg_fetch_object() when an error occurs in subroutine
This is a follow-up of GH-20068
1 parent db8c331 commit 81404a2

File tree

1 file changed

+30
-10
lines changed

1 file changed

+30
-10
lines changed

ext/pgsql/pgsql.c

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1978,7 +1978,7 @@ PHP_FUNCTION(pg_fetch_result)
19781978
/* }}} */
19791979

19801980
/* {{{ 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)
1981+
static bool php_pgsql_fetch_hash(zval *return_value, const zval *result, zend_long row, bool row_is_null, zend_long result_type)
19821982
{
19831983
PGresult *pgsql_result;
19841984
pgsql_result_handle *pg_result;
@@ -1987,31 +1987,34 @@ static void php_pgsql_fetch_hash(zval *return_value, const zval *result, zend_lo
19871987

19881988
if (!row_is_null && row < 0) {
19891989
zend_argument_value_error(2, "must be greater than or equal to 0");
1990-
RETURN_THROWS();
1990+
return false;
19911991
}
19921992

19931993
if (!(result_type & PGSQL_BOTH)) {
19941994
zend_argument_value_error(3, "must be one of PGSQL_ASSOC, PGSQL_NUM, or PGSQL_BOTH");
1995-
RETURN_THROWS();
1995+
return false;
19961996
}
19971997

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

20022005
if (!row_is_null) {
20032006
if (row >= PQntuples(pgsql_result)) {
20042007
php_error_docref(NULL, E_WARNING, "Unable to jump to row " ZEND_LONG_FMT " on PostgreSQL result index " ZEND_LONG_FMT,
20052008
row, Z_LVAL_P(result));
2006-
RETURN_FALSE;
2009+
return false;
20072010
}
20082011
pgsql_row = (int)row;
20092012
pg_result->row = pgsql_row;
20102013
} else {
20112014
/* If 2nd param is NULL, use internal row counter to access next row */
20122015
pgsql_row = pg_result->row;
20132016
if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
2014-
RETURN_FALSE;
2017+
return false;
20152018
}
20162019
pg_result->row++;
20172020
}
@@ -2042,6 +2045,7 @@ static void php_pgsql_fetch_hash(zval *return_value, const zval *result, zend_lo
20422045
}
20432046
}
20442047
}
2048+
return true;
20452049
}
20462050
/* }}} */
20472051

@@ -2060,7 +2064,11 @@ 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 php_pgsql_fetch_hash() returns true then we have a properly initialized retval */
2068+
if (UNEXPECTED(!php_pgsql_fetch_hash(return_value, result, row, row_is_null, result_type))) {
2069+
/* Either an exception is thrown, or we return false */
2070+
RETURN_FALSE;
2071+
}
20642072
}
20652073
/* }}} */
20662074

@@ -2077,7 +2085,11 @@ PHP_FUNCTION(pg_fetch_assoc)
20772085
Z_PARAM_LONG_OR_NULL(row, row_is_null)
20782086
ZEND_PARSE_PARAMETERS_END();
20792087

2080-
php_pgsql_fetch_hash(return_value, result, row, row_is_null, PGSQL_ASSOC);
2088+
/* If php_pgsql_fetch_hash() returns true then we have a properly initialized retval */
2089+
if (UNEXPECTED(!php_pgsql_fetch_hash(return_value, result, row, row_is_null, PGSQL_ASSOC))) {
2090+
/* Either an exception is thrown, or we return false */
2091+
RETURN_FALSE;
2092+
}
20812093
}
20822094
/* }}} */
20832095

@@ -2096,7 +2108,11 @@ PHP_FUNCTION(pg_fetch_array)
20962108
Z_PARAM_LONG(result_type)
20972109
ZEND_PARSE_PARAMETERS_END();
20982110

2099-
php_pgsql_fetch_hash(return_value, result, row, row_is_null, result_type);
2111+
/* If php_pgsql_fetch_hash() returns true then we have a properly initialized retval */
2112+
if (UNEXPECTED(!php_pgsql_fetch_hash(return_value, result, row, row_is_null, result_type))) {
2113+
/* Either an exception is thrown, or we return false */
2114+
RETURN_FALSE;
2115+
}
21002116
}
21012117
/* }}} */
21022118

@@ -2132,7 +2148,11 @@ PHP_FUNCTION(pg_fetch_object)
21322148
/* pg_fetch_object() allowed result_type used to be. 3rd parameter
21332149
must be allowed for compatibility */
21342150
zval dataset;
2135-
php_pgsql_fetch_hash(&dataset, result, row, row_is_null, PGSQL_ASSOC);
2151+
/* If php_pgsql_fetch_hash() returns true then we have a properly initialized retval */
2152+
if (UNEXPECTED(!php_pgsql_fetch_hash(&dataset, result, row, row_is_null, PGSQL_ASSOC))) {
2153+
/* Either an exception is thrown, or we return false */
2154+
RETURN_FALSE;
2155+
}
21362156

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

0 commit comments

Comments
 (0)