From a9ab01f1a216d82bbc421ce0933ad07382c3adfa Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 14 Nov 2021 15:01:58 +0000 Subject: [PATCH 1/3] pgsql ext: pg_query_params/pg_send_query_params false constant handling proposal. --- ext/pgsql/tests/33query_params_bool.phpt | 28 ++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 ext/pgsql/tests/33query_params_bool.phpt diff --git a/ext/pgsql/tests/33query_params_bool.phpt b/ext/pgsql/tests/33query_params_bool.phpt new file mode 100644 index 000000000000..e8f99bb518b9 --- /dev/null +++ b/ext/pgsql/tests/33query_params_bool.phpt @@ -0,0 +1,28 @@ +--TEST-- +PostgreSQL prepared queries with bool constants +--SKIPIF-- + +--FILE-- += 3) { + $result = pg_query_params($db, "SELECT * FROM ".$table_name." WHERE num >= $1;", array(true)); + // bug occurs with false as it turns out as empty. + $result = pg_query_params($db, "SELECT * FROM ".$table_name." WHERE num <> $1;", array(false)); + pg_free_result($result); +} +pg_close($db); + +echo "OK"; +?> +--EXPECT-- +OK + From 81967a2617242f57e109f4cf7a85c9cce68f5277 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 1 Apr 2022 18:51:21 +0100 Subject: [PATCH 2/3] pdo update --- ext/pdo/pdo_stmt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index a8564cd8d39c..3f96134be680 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -269,9 +269,14 @@ static bool really_register_bound_param(struct pdo_bound_param_data *param, pdo_ } if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_STR && param->max_value_len <= 0 && !Z_ISNULL_P(parameter)) { + zend_bool is_false = (Z_TYPE_P(parameter) == IS_FALSE); if (!try_convert_to_string(parameter)) { return false; } + /* the pgsql's driver does not handle empty string for false bound parameters */ + if (is_false) { + ZVAL_STR(parameter, ZSTR_CHAR('0')); + } } else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_INT && (Z_TYPE_P(parameter) == IS_FALSE || Z_TYPE_P(parameter) == IS_TRUE)) { convert_to_long(parameter); } else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_BOOL && Z_TYPE_P(parameter) == IS_LONG) { From ad95c4b19910d1ff30aa77d9fdbb866d2d63f406 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 12 Apr 2026 19:02:56 +0100 Subject: [PATCH 3/3] feedback --- ext/pdo/pdo_stmt.c | 5 ---- ext/pgsql/pgsql.c | 14 +++++++---- ext/pgsql/tests/33query_params_bool.phpt | 31 ++++++++++++++---------- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 3f96134be680..a8564cd8d39c 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -269,14 +269,9 @@ static bool really_register_bound_param(struct pdo_bound_param_data *param, pdo_ } if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_STR && param->max_value_len <= 0 && !Z_ISNULL_P(parameter)) { - zend_bool is_false = (Z_TYPE_P(parameter) == IS_FALSE); if (!try_convert_to_string(parameter)) { return false; } - /* the pgsql's driver does not handle empty string for false bound parameters */ - if (is_false) { - ZVAL_STR(parameter, ZSTR_CHAR('0')); - } } else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_INT && (Z_TYPE_P(parameter) == IS_FALSE || Z_TYPE_P(parameter) == IS_TRUE)) { convert_to_long(parameter); } else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_BOOL && Z_TYPE_P(parameter) == IS_LONG) { diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 27c736348239..b0854067750d 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -1241,7 +1241,7 @@ static void _php_pgsql_free_params(char **params, uint32_t num_params) efree(params); } -static char **php_pgsql_make_arguments(const HashTable *param_arr, int *num_params) +static char **php_pgsql_make_arguments(const HashTable *param_arr, int *num_params, uint32_t arg_num) { /* This conversion is safe because of the limit of number of elements in a table. */ *num_params = (int) zend_hash_num_elements(param_arr); @@ -1252,6 +1252,10 @@ static char **php_pgsql_make_arguments(const HashTable *param_arr, int *num_para ZVAL_DEREF(tmp); if (Z_TYPE_P(tmp) == IS_NULL) { params[i] = NULL; + } else if (Z_TYPE_P(tmp) == IS_TRUE || Z_TYPE_P(tmp) == IS_FALSE) { + zend_argument_value_error(arg_num, "must not contain boolean values, use a string representation instead"); + _php_pgsql_free_params(params, i); + return NULL; } else { zend_string *param_str = zval_try_get_string(tmp); if (!param_str) { @@ -1318,7 +1322,7 @@ PHP_FUNCTION(pg_query_params) php_error_docref(NULL, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first"); } - params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params); + params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params, ZEND_NUM_ARGS()); if (UNEXPECTED(!params)) { RETURN_THROWS(); } @@ -1501,7 +1505,7 @@ PHP_FUNCTION(pg_execute) php_error_docref(NULL, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first"); } - params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params); + params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params, ZEND_NUM_ARGS()); if (UNEXPECTED(!params)) { RETURN_THROWS(); } @@ -4058,7 +4062,7 @@ PHP_FUNCTION(pg_send_query_params) "There are results on this connection. Call pg_get_result() until it returns FALSE"); } - params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params); + params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params, 3); if (UNEXPECTED(!params)) { RETURN_THROWS(); } @@ -4213,7 +4217,7 @@ PHP_FUNCTION(pg_send_execute) "There are results on this connection. Call pg_get_result() until it returns FALSE"); } - params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params); + params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params, 3); if (UNEXPECTED(!params)) { RETURN_THROWS(); } diff --git a/ext/pgsql/tests/33query_params_bool.phpt b/ext/pgsql/tests/33query_params_bool.phpt index e8f99bb518b9..1be512cd44bb 100644 --- a/ext/pgsql/tests/33query_params_bool.phpt +++ b/ext/pgsql/tests/33query_params_bool.phpt @@ -1,28 +1,33 @@ --TEST-- -PostgreSQL prepared queries with bool constants +PostgreSQL pg_query_params bool parameter rejection +--EXTENSIONS-- +pgsql --SKIPIF-- - + --FILE-- = 3) { - $result = pg_query_params($db, "SELECT * FROM ".$table_name." WHERE num >= $1;", array(true)); - // bug occurs with false as it turns out as empty. - $result = pg_query_params($db, "SELECT * FROM ".$table_name." WHERE num <> $1;", array(false)); - pg_free_result($result); +try { + pg_query_params($db, "SELECT * FROM ".$table_name." WHERE num >= $1;", array(true)); +} catch (ValueError $e) { + echo $e->getMessage() . "\n"; +} + +try { + pg_query_params($db, "SELECT * FROM ".$table_name." WHERE num <> $1;", array(false)); +} catch (ValueError $e) { + echo $e->getMessage() . "\n"; } + pg_close($db); echo "OK"; ?> --EXPECT-- +pg_query_params(): Argument #3 ($params) must not contain boolean values, use a string representation instead +pg_query_params(): Argument #3 ($params) must not contain boolean values, use a string representation instead OK -