From a2fcf369322a7f01c5df579570e03643dca6d5fe Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Fri, 12 Mar 2021 20:41:15 +0000 Subject: [PATCH 1/3] Validate string is numeric for integer PDO attribute value --- UPGRADING.INTERNALS | 3 ++ ext/pdo/pdo_dbh.c | 53 +++++++++++++------ ext/pdo/php_pdo_driver.h | 3 ++ ext/pdo/tests/bug_44159.phpt | 2 +- .../tests/pdo_mysql_attr_errmode.phpt | 2 +- .../tests/pdo_mysql_attr_oracle_nulls.phpt | 2 +- 6 files changed, 46 insertions(+), 19 deletions(-) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 2c5d1a944de6d..8198efc1eb21b 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -68,3 +68,6 @@ PHP 8.1 INTERNALS UPGRADE NOTES of char* for the optional sequence/table name. - The php_pdo_str_tolower_dup() PDO_API has been removed use zend_str_tolower_dup() or zend_string_tolower_ex(). + - A new PDO_API pdo_get_long_param(zend_long *lval, zval *value) has been + introduced to fetch integer values for driver attributes, it will throw + a type error and return false in case of failure. diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 41ac1e260e878..60b6ebcf3ff19 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -678,12 +678,24 @@ PHP_METHOD(PDO, inTransaction) } /* }}} */ -/* TODO: Make distinction between numeric and non-numeric strings */ -#define PDO_LONG_PARAM_CHECK \ - if (Z_TYPE_P(value) != IS_LONG && Z_TYPE_P(value) != IS_STRING && Z_TYPE_P(value) != IS_FALSE && Z_TYPE_P(value) != IS_TRUE) { \ - zend_type_error("Attribute value must be of type int for selected attribute, %s given", zend_zval_type_name(value)); \ - return false; \ - } \ +PDO_API bool pdo_get_long_param(zend_long *lval, zval *value) +{ + switch (Z_TYPE_P(value)) { + case IS_LONG: + case IS_TRUE: + case IS_FALSE: + *lval = zval_get_long(value); + return true; + case IS_STRING: + if (IS_LONG == is_numeric_str_function(Z_STR_P(value), lval, NULL)) { + return true; + } + /* fallthrough */ + default: + zend_type_error("Attribute value must be of type int 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) /* {{{ */ @@ -692,8 +704,9 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) / switch (attr) { case PDO_ATTR_ERRMODE: - PDO_LONG_PARAM_CHECK; - lval = zval_get_long(value); + if (!pdo_get_long_param(&lval, value)) { + return false; + } switch (lval) { case PDO_ERRMODE_SILENT: case PDO_ERRMODE_WARNING: @@ -707,8 +720,9 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) / return false; case PDO_ATTR_CASE: - PDO_LONG_PARAM_CHECK; - lval = zval_get_long(value); + if (!pdo_get_long_param(&lval, value)) { + return false; + } switch (lval) { case PDO_CASE_NATURAL: case PDO_CASE_UPPER: @@ -722,8 +736,10 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) / return false; case PDO_ATTR_ORACLE_NULLS: - PDO_LONG_PARAM_CHECK; - dbh->oracle_nulls = zval_get_long(value); + if (!pdo_get_long_param(&lval, value)) { + return false; + } + dbh->oracle_nulls = lval; return true; case PDO_ATTR_DEFAULT_FETCH_MODE: @@ -735,10 +751,12 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) / return false; } } + lval = zval_get_long(value); } else { - PDO_LONG_PARAM_CHECK; + if (!pdo_get_long_param(&lval, value)) { + return false; + } } - lval = zval_get_long(value); if (lval == PDO_FETCH_USE_DEFAULT) { zend_value_error("Fetch mode must be a bitmask of PDO::FETCH_* constants"); return false; @@ -747,8 +765,11 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) / return true; case PDO_ATTR_STRINGIFY_FETCHES: - PDO_LONG_PARAM_CHECK; - dbh->stringify = zval_get_long(value) ? 1 : 0; + if (pdo_get_long_param(&lval, value) == false) { + return false; + } + /* TODO Check for proper boolean value? */ + dbh->stringify = lval ? 1 : 0; return true; case PDO_ATTR_STATEMENT_CLASS: { diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h index 91a71bd8f58a0..cb73db86d739b 100644 --- a/ext/pdo/php_pdo_driver.h +++ b/ext/pdo/php_pdo_driver.h @@ -681,5 +681,8 @@ PDO_API void php_pdo_dbh_delref(pdo_dbh_t *dbh); PDO_API void php_pdo_free_statement(pdo_stmt_t *stmt); 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 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 b5601eed41c47..4167220efdfe5 100644 --- a/ext/pdo/tests/bug_44159.phpt +++ b/ext/pdo/tests/bug_44159.phpt @@ -44,4 +44,4 @@ 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 bool(true) -bool(true) +TypeError: Attribute value must be of type int for selected attribute, string given diff --git a/ext/pdo_mysql/tests/pdo_mysql_attr_errmode.phpt b/ext/pdo_mysql/tests/pdo_mysql_attr_errmode.phpt index d6ebd87f60327..fc4f2f0808c14 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_attr_errmode.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_attr_errmode.phpt @@ -25,7 +25,6 @@ error_reporting=E_ALL echo get_class($e), ': ', $e->getMessage(), \PHP_EOL; } try { - /* This currently passes */ $db->setAttribute(PDO::ATTR_ERRMODE, 'pdo'); } catch (\Error $e) { echo get_class($e), ': ', $e->getMessage(), \PHP_EOL; @@ -160,6 +159,7 @@ error_reporting=E_ALL --EXPECTF-- TypeError: Attribute value must be of type int for selected attribute, array given TypeError: Attribute value must be of type int for selected attribute, stdClass given +TypeError: Attribute value must be of type int for selected attribute, string given ValueError: Error mode must be one of the PDO::ERRMODE_* constants Warning: PDO::query(): SQLSTATE[42000]: Syntax error or access violation: %d You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near '%s' at line %d in %s on line %d diff --git a/ext/pdo_mysql/tests/pdo_mysql_attr_oracle_nulls.phpt b/ext/pdo_mysql/tests/pdo_mysql_attr_oracle_nulls.phpt index d7f54bfdee940..78d6ae7879544 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_attr_oracle_nulls.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_attr_oracle_nulls.phpt @@ -23,7 +23,6 @@ MySQLPDOTest::skip(); echo $e->getMessage(), \PHP_EOL; } try { - /* Currently passes... */ $db->setAttribute(PDO::ATTR_ORACLE_NULLS, 'pdo'); } catch (\TypeError $e) { echo $e->getMessage(), \PHP_EOL; @@ -72,6 +71,7 @@ MySQLPDOTest::skip(); --EXPECTF-- Attribute value must be of type int for selected attribute, array given Attribute value must be of type int for selected attribute, stdClass given +Attribute value must be of type int for selected attribute, string given array(1) { [0]=> array(6) { From 5cb01f428d3730b0aae31abdb1f2e1337dcab264 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Mon, 15 Mar 2021 15:30:58 +0000 Subject: [PATCH 2/3] Use standard PDO way for fetching integer attribute values --- ext/pdo_dblib/dblib_driver.c | 21 +++++++++++++++---- ext/pdo_firebird/firebird_driver.c | 1 + ext/pdo_mysql/mysql_driver.c | 12 +++++++++-- ext/pdo_oci/oci_driver.c | 13 +++++++++++- ext/pdo_sqlite/sqlite_driver.c | 11 ++++++++-- .../tests/bug_44159_sqlite_version.phpt | 16 ++++++++++---- 6 files changed, 61 insertions(+), 13 deletions(-) diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c index ae45da6beb425..b65694c045f26 100644 --- a/ext/pdo_dblib/dblib_driver.c +++ b/ext/pdo_dblib/dblib_driver.c @@ -273,22 +273,35 @@ zend_string *dblib_handle_last_id(pdo_dbh_t *dbh, const zend_string *name) 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; switch(attr) { case PDO_ATTR_DEFAULT_STR_PARAM: - H->assume_national_character_set_strings = zval_get_long(val) == PDO_PARAM_STR_NATL ? 1 : 0; + if (!pdo_get_long_param(&lval, val)) { + return false; + } + H->assume_national_character_set_strings = lval == PDO_PARAM_STR_NATL ? 1 : 0; return true; case PDO_ATTR_TIMEOUT: case PDO_DBLIB_ATTR_QUERY_TIMEOUT: - return SUCCEED == dbsettime(zval_get_long(val)); + if (!pdo_get_long_param(&lval, val)) { + return false; + } + return SUCCEED == dbsettime(lval); case PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER: - H->stringify_uniqueidentifier = zval_get_long(val); + if (!pdo_get_long_param(&lval, val)) { + return false; + } + H->stringify_uniqueidentifier = lval; return true; case PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS: H->skip_empty_rowsets = zval_is_true(val); return true; case PDO_DBLIB_ATTR_DATETIME_CONVERT: - H->datetime_convert = zval_get_long(val); + if (!pdo_get_long_param(&lval, val)) { + return false; + } + H->datetime_convert = lval; return true; default: return false; diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index 338aa88ec95e8..4bc3ea42b698b 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -824,6 +824,7 @@ static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval * 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; /* ignore if the new value equals the old one */ diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c index 94fa2411d67a4..74a24be399469 100644 --- a/ext/pdo_mysql/mysql_driver.c +++ b/ext/pdo_mysql/mysql_driver.c @@ -402,11 +402,13 @@ static inline int mysql_handle_autocommit(pdo_dbh_t *dbh) /* {{{ pdo_mysql_set_attribute */ static bool pdo_mysql_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) { - zend_long lval = zval_get_long(val); - bool bval = lval ? 1 : 0; + 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; 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: /* ignore if the new value equals the old one */ @@ -419,6 +421,9 @@ static bool pdo_mysql_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) PDO_DBG_RETURN(true); case PDO_ATTR_DEFAULT_STR_PARAM: + if (!pdo_get_long_param(&lval, val)) { + PDO_DBG_RETURN(false); + } ((pdo_mysql_db_handle *)dbh->driver_data)->assume_national_character_set_strings = lval == PDO_PARAM_STR_NATL; PDO_DBG_RETURN(true); @@ -439,6 +444,9 @@ static bool pdo_mysql_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) #ifndef PDO_USE_MYSQLND case PDO_MYSQL_ATTR_MAX_BUFFER_SIZE: + if (!pdo_get_long_param(&lval, val)) { + PDO_DBG_RETURN(false); + } if (lval < 0) { /* TODO: Johannes, can we throw a warning here? */ ((pdo_mysql_db_handle *)dbh->driver_data)->max_buffer_size = 1024*1024; diff --git a/ext/pdo_oci/oci_driver.c b/ext/pdo_oci/oci_driver.c index dd4a7bb171318..524820b910698 100644 --- a/ext/pdo_oci/oci_driver.c +++ b/ext/pdo_oci/oci_driver.c @@ -425,12 +425,16 @@ static bool oci_handle_rollback(pdo_dbh_t *dbh) /* {{{ */ static bool oci_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) /* {{{ */ { - zend_long lval = zval_get_long(val); + zend_long lval; pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data; switch (attr) { case PDO_ATTR_AUTOCOMMIT: { + if (pdo_get_long_param(&lval, val) == false) { + return false; + } + if (dbh->in_txn) { /* Assume they want to commit whatever is outstanding */ H->last_err = OCITransCommit(H->svc, H->err, 0); @@ -447,6 +451,10 @@ static bool oci_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) } case PDO_ATTR_PREFETCH: { + if (!pdo_get_long_param(&lval, val)) { + return false; + } + H->prefetch = pdo_oci_sanitize_prefetch(lval); return true; } @@ -537,6 +545,9 @@ static bool oci_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) case PDO_OCI_ATTR_CALL_TIMEOUT: { #if (OCI_MAJOR_VERSION >= 18) + if (!pdo_get_long_param(&lval, val)) { + return false; + } ub4 timeout = (ub4) lval; H->last_err = OCIAttrSet(H->svc, OCI_HTYPE_SVCCTX, diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c index 217833f6ad8ca..b7c20b1eae856 100644 --- a/ext/pdo_sqlite/sqlite_driver.c +++ b/ext/pdo_sqlite/sqlite_driver.c @@ -294,13 +294,20 @@ static int pdo_sqlite_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return static bool pdo_sqlite_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val) { pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data; + zend_long lval; switch (attr) { case PDO_ATTR_TIMEOUT: - sqlite3_busy_timeout(H->db, zval_get_long(val) * 1000); + if (!pdo_get_long_param(&lval, val)) { + return false; + } + sqlite3_busy_timeout(H->db, lval * 1000); return true; case PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES: - sqlite3_extended_result_codes(H->db, zval_get_long(val)); + if (!pdo_get_long_param(&lval, val)) { + return false; + } + sqlite3_extended_result_codes(H->db, lval); return true; } return false; diff --git a/ext/pdo_sqlite/tests/bug_44159_sqlite_version.phpt b/ext/pdo_sqlite/tests/bug_44159_sqlite_version.phpt index fc30f1d21cc23..dbb4b6cf7dda8 100644 --- a/ext/pdo_sqlite/tests/bug_44159_sqlite_version.phpt +++ b/ext/pdo_sqlite/tests/bug_44159_sqlite_version.phpt @@ -9,14 +9,22 @@ if (!extension_loaded('pdo_sqlite')) die('skip PDO SQLite not available'); $pdo = new PDO("sqlite:".__DIR__."/foo.db"); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); -var_dump($pdo->setAttribute(PDO::NULL_TO_STRING, NULL)); +try { + var_dump($pdo->setAttribute(PDO::NULL_TO_STRING, NULL)); +} catch (\TypeError $e) { + echo $e->getMessage(), \PHP_EOL; +} var_dump($pdo->setAttribute(PDO::NULL_TO_STRING, 1)); -var_dump($pdo->setAttribute(PDO::NULL_TO_STRING, 'nonsense')); +try { + var_dump($pdo->setAttribute(PDO::NULL_TO_STRING, 'nonsense')); +} catch (\TypeError $e) { + echo $e->getMessage(), \PHP_EOL; +} @unlink(__DIR__."/foo.db"); ?> --EXPECT-- +Attribute value must be of type int for selected attribute, null given bool(true) -bool(true) -bool(true) +Attribute value must be of type int for selected attribute, string given From 9b183aff6d0720316164e68ce1f99aa36551aa06 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Mon, 15 Mar 2021 16:26:04 +0000 Subject: [PATCH 3/3] Add API to fetch bool value for PDO attribute values --- UPGRADING.INTERNALS | 3 +++ 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 +++++++- 10 files changed, 70 insertions(+), 15 deletions(-) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 8198efc1eb21b..621d42d2b72e6 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -71,3 +71,6 @@ PHP 8.1 INTERNALS UPGRADE NOTES - A new PDO_API pdo_get_long_param(zend_long *lval, zval *value) has been introduced to fetch integer values for driver attributes, it will throw a type error and return false in case of failure. + - A new PDO_API pdo_get_bool_param(zend_long *bool, zval *value) has been + introduced to fetch boolean values for driver attributes, it will throw + a type error and return false in case of failure. diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 60b6ebcf3ff19..73a1c8aa174fc 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 cb73db86d739b..c1a01b3400754 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 4167220efdfe5..d80311ad22103 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 b65694c045f26..712a6e11d0391 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 4bc3ea42b698b..deee7f33f3f28 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 74a24be399469..7bc0cbcf0a54e 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 524820b910698..36f6654a356c7 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 719aa36219a29..790ee87851639 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 5f2827334a86e..1c511c1d47972 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: