From ebaeb93c3f9f23aa9b2e5ccc1f8bf17ec3700bf2 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Mon, 15 Mar 2021 16:26:04 +0000 Subject: [PATCH] Add API to fetch bool value for PDO attribute values Closes GH-6766 --- ext/pdo/pdo_dbh.c | 25 ++++++++++++++++++++++--- ext/pdo/php_pdo_driver.h | 1 + ext/pdo/tests/bug_44159.phpt | 4 ++-- ext/pdo_dblib/dblib_driver.c | 6 +++++- ext/pdo_firebird/firebird_driver.c | 11 ++++++++--- ext/pdo_mysql/mysql_driver.c | 15 +++++++++++++-- ext/pdo_oci/oci_driver.c | 5 +++-- ext/pdo_odbc/odbc_driver.c | 7 ++++++- ext/pdo_pgsql/pgsql_driver.c | 8 +++++++- 9 files changed, 67 insertions(+), 15 deletions(-) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 60b6ebcf3f..73a1c8aa17 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -696,11 +696,30 @@ PDO_API bool pdo_get_long_param(zend_long *lval, zval *value) return false; } } +PDO_API bool pdo_get_bool_param(bool *bval, zval *value) +{ + switch (Z_TYPE_P(value)) { + case IS_TRUE: + *bval = true; + return true; + case IS_FALSE: + *bval = false; + return true; + case IS_LONG: + *bval = zval_is_true(value); + return true; + case IS_STRING: /* TODO Should string be allowed? */ + default: + zend_type_error("Attribute value must be of type bool for selected attribute, %s given", zend_zval_type_name(value)); + return false; + } +} /* Return false on failure, true otherwise */ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /* {{{ */ { zend_long lval; + bool bval; switch (attr) { case PDO_ATTR_ERRMODE: @@ -739,6 +758,7 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) / if (!pdo_get_long_param(&lval, value)) { return false; } + /* TODO Check for valid value (NULL_NATURAL, NULL_EMPTY_STRING, NULL_TO_STRING)? */ dbh->oracle_nulls = lval; return true; @@ -765,11 +785,10 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) / return true; case PDO_ATTR_STRINGIFY_FETCHES: - if (pdo_get_long_param(&lval, value) == false) { + if (!pdo_get_bool_param(&bval, value)) { return false; } - /* TODO Check for proper boolean value? */ - dbh->stringify = lval ? 1 : 0; + dbh->stringify = bval; return true; case PDO_ATTR_STATEMENT_CLASS: { diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h index cb73db86d7..c1a01b3400 100644 --- a/ext/pdo/php_pdo_driver.h +++ b/ext/pdo/php_pdo_driver.h @@ -683,6 +683,7 @@ PDO_API void php_pdo_stmt_set_column_count(pdo_stmt_t *stmt, int new_count); /* Normalization for fetching long param for driver attributes */ PDO_API bool pdo_get_long_param(zend_long *lval, zval *value); +PDO_API bool pdo_get_bool_param(bool *bval, zval *value); PDO_API void pdo_throw_exception(unsigned int driver_errcode, char *driver_errmsg, pdo_error_type *pdo_error); #endif /* PHP_PDO_DRIVER_H */ diff --git a/ext/pdo/tests/bug_44159.phpt b/ext/pdo/tests/bug_44159.phpt index 4167220efd..d80311ad22 100644 --- a/ext/pdo/tests/bug_44159.phpt +++ b/ext/pdo/tests/bug_44159.phpt @@ -42,6 +42,6 @@ foreach ($attrs as $attr) { TypeError: PDO::ATTR_STATEMENT_CLASS value must be of type array, null given TypeError: PDO::ATTR_STATEMENT_CLASS value must be of type array, int given TypeError: PDO::ATTR_STATEMENT_CLASS value must be of type array, string given -TypeError: Attribute value must be of type int for selected attribute, null given +TypeError: Attribute value must be of type bool for selected attribute, null given bool(true) -TypeError: Attribute value must be of type int for selected attribute, string given +TypeError: Attribute value must be of type bool for selected attribute, string given diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c index b65694c045..712a6e11d0 100644 --- a/ext/pdo_dblib/dblib_driver.c +++ b/ext/pdo_dblib/dblib_driver.c @@ -274,6 +274,7 @@ static bool dblib_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val) { pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data; zend_long lval; + bool bval; switch(attr) { case PDO_ATTR_DEFAULT_STR_PARAM: @@ -295,7 +296,10 @@ static bool dblib_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val) H->stringify_uniqueidentifier = lval; return true; case PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS: - H->skip_empty_rowsets = zval_is_true(val); + if (!pdo_get_bool_param(&bval, val)) { + return false; + } + H->skip_empty_rowsets = bval; return true; case PDO_DBLIB_ATTR_DATETIME_CONVERT: if (!pdo_get_long_param(&lval, val)) { diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index 4bc3ea42b6..deee7f33f3 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -820,12 +820,14 @@ static int firebird_alloc_prepare_stmt(pdo_dbh_t *dbh, const zend_string *sql, static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) /* {{{ */ { pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; + bool bval; switch (attr) { case PDO_ATTR_AUTOCOMMIT: { - /* Don't use pdo_get_long_param() API as zval_get_long accepts more things */ - bool bval = zval_get_long(val)? 1 : 0; + if (!pdo_get_bool_param(&bval, val)) { + return false; + } /* ignore if the new value equals the old one */ if (dbh->auto_commit ^ bval) { @@ -849,7 +851,10 @@ static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval * return true; case PDO_ATTR_FETCH_TABLE_NAMES: - H->fetch_table_names = zval_get_long(val)? 1 : 0; + if (!pdo_get_bool_param(&bval, val)) { + return false; + } + H->fetch_table_names = bval; return true; case PDO_FB_ATTR_DATE_FORMAT: diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c index 74a24be399..7bc0cbcf0a 100644 --- a/ext/pdo_mysql/mysql_driver.c +++ b/ext/pdo_mysql/mysql_driver.c @@ -403,14 +403,16 @@ static inline int mysql_handle_autocommit(pdo_dbh_t *dbh) static bool pdo_mysql_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) { zend_long lval; - /* Don't use pdo_get_long_param() API as zval_get_long accepts more things */ - bool bval = zval_get_long(val) ? 1 : 0; + bool bval; PDO_DBG_ENTER("pdo_mysql_set_attribute"); PDO_DBG_INF_FMT("dbh=%p", dbh); PDO_DBG_INF_FMT("attr=%l", attr); switch (attr) { case PDO_ATTR_AUTOCOMMIT: + if (!pdo_get_bool_param(&bval, val)) { + return false; + } /* ignore if the new value equals the old one */ if (dbh->auto_commit ^ bval) { dbh->auto_commit = bval; @@ -428,17 +430,26 @@ static bool pdo_mysql_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) PDO_DBG_RETURN(true); case PDO_MYSQL_ATTR_USE_BUFFERED_QUERY: + if (!pdo_get_bool_param(&bval, val)) { + return false; + } /* ignore if the new value equals the old one */ ((pdo_mysql_db_handle *)dbh->driver_data)->buffered = bval; PDO_DBG_RETURN(true); case PDO_MYSQL_ATTR_DIRECT_QUERY: case PDO_ATTR_EMULATE_PREPARES: + if (!pdo_get_bool_param(&bval, val)) { + return false; + } /* ignore if the new value equals the old one */ ((pdo_mysql_db_handle *)dbh->driver_data)->emulate_prepare = bval; PDO_DBG_RETURN(true); case PDO_ATTR_FETCH_TABLE_NAMES: + if (!pdo_get_bool_param(&bval, val)) { + return false; + } ((pdo_mysql_db_handle *)dbh->driver_data)->fetch_table_names = bval; PDO_DBG_RETURN(true); diff --git a/ext/pdo_oci/oci_driver.c b/ext/pdo_oci/oci_driver.c index 524820b910..36f6654a35 100644 --- a/ext/pdo_oci/oci_driver.c +++ b/ext/pdo_oci/oci_driver.c @@ -431,7 +431,8 @@ static bool oci_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) switch (attr) { case PDO_ATTR_AUTOCOMMIT: { - if (pdo_get_long_param(&lval, val) == false) { + bool bval; + if (!pdo_get_bool_param(&bval, val)) { return false; } @@ -446,7 +447,7 @@ static bool oci_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) dbh->in_txn = false; } - dbh->auto_commit = (unsigned int)lval? 1 : 0; + dbh->auto_commit = (unsigned int) bval; return true; } case PDO_ATTR_PREFETCH: diff --git a/ext/pdo_odbc/odbc_driver.c b/ext/pdo_odbc/odbc_driver.c index 719aa36219..790ee87851 100644 --- a/ext/pdo_odbc/odbc_driver.c +++ b/ext/pdo_odbc/odbc_driver.c @@ -333,9 +333,14 @@ static bool odbc_handle_rollback(pdo_dbh_t *dbh) static bool odbc_handle_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val) { pdo_odbc_db_handle *H = (pdo_odbc_db_handle *)dbh->driver_data; + bool bval; + switch (attr) { case PDO_ODBC_ATTR_ASSUME_UTF8: - H->assume_utf8 = zval_is_true(val); + if (!pdo_get_bool_param(&bval, val)) { + return false; + } + H->assume_utf8 = bval; return true; default: strcpy(H->einfo.last_err_msg, "Unknown Attribute"); diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index 5f2827334a..1c511c1d47 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -1154,14 +1154,20 @@ static const zend_function_entry *pdo_pgsql_get_driver_methods(pdo_dbh_t *dbh, i static bool pdo_pgsql_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val) { - bool bval = zval_get_long(val)? 1 : 0; + bool bval; pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; switch (attr) { case PDO_ATTR_EMULATE_PREPARES: + if (!pdo_get_bool_param(&bval, val)) { + return false; + } H->emulate_prepares = bval; return true; case PDO_PGSQL_ATTR_DISABLE_PREPARES: + if (!pdo_get_bool_param(&bval, val)) { + return false; + } H->disable_prepares = bval; return true; default: -- 2.50.1