mbeccati Thu Apr 2 16:41:24 2009 UTC Added files: (Branch: PHP_5_3) /php-src/ext/pdo/tests bug_44173.phpt
Modified files: /php-src NEWS /php-src/ext/pdo pdo_dbh.c pdo_stmt.c Log: MFH: - Fixed bug #44173 (PDO->query() parameter parsing/checking needs an update) # The changeset is longer than really needed because pdo_stmt.c was # refactored to remove the "goto"
http://cvs.php.net/viewvc.cgi/php-src/NEWS?r1=1.2027.2.547.2.965.2.550&r2=1.2027.2.547.2.965.2.551&diff_format=u Index: php-src/NEWS diff -u php-src/NEWS:1.2027.2.547.2.965.2.550 php-src/NEWS:1.2027.2.547.2.965.2.551 --- php-src/NEWS:1.2027.2.547.2.965.2.550 Thu Apr 2 09:56:33 2009 +++ php-src/NEWS Thu Apr 2 16:41:23 2009 @@ -25,6 +25,8 @@ - Fixed bug #47038 (Memory leak in include). (Dmitry) - Fixed bug #44861 (scrollable cursor don't work with pgsql). (Matteo) - Fixed bug #44409 (PDO::FETCH_SERIALIZE calls __construct()). (Matteo) +- Fixed bug #44173 (PDO->query() parameter parsing/checking needs an + update). (Matteo) - Fixed bug #42362 (HTTP status codes 204 and 304 should not be gzipped). (Scott, Edward Z. Yang) http://cvs.php.net/viewvc.cgi/php-src/ext/pdo/pdo_dbh.c?r1=1.82.2.31.2.17.2.23&r2=1.82.2.31.2.17.2.24&diff_format=u Index: php-src/ext/pdo/pdo_dbh.c diff -u php-src/ext/pdo/pdo_dbh.c:1.82.2.31.2.17.2.23 php-src/ext/pdo/pdo_dbh.c:1.82.2.31.2.17.2.24 --- php-src/ext/pdo/pdo_dbh.c:1.82.2.31.2.17.2.23 Thu Mar 26 12:53:39 2009 +++ php-src/ext/pdo/pdo_dbh.c Thu Apr 2 16:41:23 2009 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: pdo_dbh.c,v 1.82.2.31.2.17.2.23 2009/03/26 12:53:39 felipe Exp $ */ +/* $Id: pdo_dbh.c,v 1.82.2.31.2.17.2.24 2009/04/02 16:41:23 mbeccati Exp $ */ /* The PDO Database Handle Class */ @@ -1065,6 +1065,12 @@ char *statement; int statement_len; + /* Return a meaningful error when no parameters were passed */ + if (!ZEND_NUM_ARGS()) { + zend_parse_parameters(0 TSRMLS_CC, "z|z", NULL, NULL); + RETURN_FALSE; + } + if (FAILURE == zend_parse_parameters(1 TSRMLS_CC, "s", &statement, &statement_len)) { RETURN_FALSE; @@ -1095,8 +1101,8 @@ ZVAL_NULL(&stmt->lazy_object_ref); if (dbh->methods->preparer(dbh, statement, statement_len, stmt, NULL TSRMLS_CC)) { + PDO_STMT_CLEAR_ERR(); if (ZEND_NUM_ARGS() == 1 || SUCCESS == pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAM_PASSTHRU, stmt, 1)) { - PDO_STMT_CLEAR_ERR(); /* now execute the statement */ PDO_STMT_CLEAR_ERR(); http://cvs.php.net/viewvc.cgi/php-src/ext/pdo/pdo_stmt.c?r1=1.118.2.38.2.24.2.44&r2=1.118.2.38.2.24.2.45&diff_format=u Index: php-src/ext/pdo/pdo_stmt.c diff -u php-src/ext/pdo/pdo_stmt.c:1.118.2.38.2.24.2.44 php-src/ext/pdo/pdo_stmt.c:1.118.2.38.2.24.2.45 --- php-src/ext/pdo/pdo_stmt.c:1.118.2.38.2.24.2.44 Mon Mar 23 23:15:02 2009 +++ php-src/ext/pdo/pdo_stmt.c Thu Apr 2 16:41:23 2009 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: pdo_stmt.c,v 1.118.2.38.2.24.2.44 2009/03/23 23:15:02 felipe Exp $ */ +/* $Id: pdo_stmt.c,v 1.118.2.38.2.24.2.45 2009/04/02 16:41:23 mbeccati Exp $ */ /* The PDO Statement Handle Class */ @@ -1951,6 +1951,7 @@ int flags, argc = ZEND_NUM_ARGS() - skip; zval ***args; zend_class_entry **cep; + int retval; do_fetch_opt_finish(stmt, 1 TSRMLS_CC); @@ -1973,21 +1974,27 @@ args = safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval*), 0); - if (FAILURE == zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args)) { -fail_out: - efree(args); - return FAILURE; - } + retval = zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args); - convert_to_long_ex(args[skip]); - mode = Z_LVAL_PP(args[skip]); - flags = mode & PDO_FETCH_FLAGS; + if (SUCCESS == retval) { + if (Z_TYPE_PP(args[skip]) != IS_LONG) { + pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "mode must be an integer" TSRMLS_CC); + retval = FAILURE; + } else { + mode = Z_LVAL_PP(args[skip]); + flags = mode & PDO_FETCH_FLAGS; - if (!pdo_stmt_verify_mode(stmt, mode, 0 TSRMLS_CC)) { + retval = pdo_stmt_verify_mode(stmt, mode, 0 TSRMLS_CC); + } + } + + if (FAILURE == retval) { + PDO_STMT_CLEAR_ERR(); efree(args); return FAILURE; } + retval = FAILURE; switch (mode & ~PDO_FETCH_FLAGS) { case PDO_FETCH_USE_DEFAULT: case PDO_FETCH_LAZY: @@ -1998,89 +2005,120 @@ case PDO_FETCH_BOUND: case PDO_FETCH_NAMED: case PDO_FETCH_KEY_PAIR: + if (argc != 1) { + pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode doesn't allow any extra arguments" TSRMLS_CC); + } else { + retval = SUCCESS; + } break; case PDO_FETCH_COLUMN: if (argc != 2) { - goto fail_out; + pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode requires the colno argument" TSRMLS_CC); + } else if (Z_TYPE_PP(args[skip+1]) != IS_LONG) { + pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "colno must be an integer" TSRMLS_CC); + } else { + stmt->fetch.column = Z_LVAL_PP(args[skip+1]); + retval = SUCCESS; } - convert_to_long_ex(args[skip+1]); - stmt->fetch.column = Z_LVAL_PP(args[skip+1]); break; case PDO_FETCH_CLASS: /* Gets its class name from 1st column */ if ((flags & PDO_FETCH_CLASSTYPE) == PDO_FETCH_CLASSTYPE) { if (argc != 1) { - goto fail_out; + pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode doesn't allow any extra arguments" TSRMLS_CC); + } else { + stmt->fetch.cls.ce = NULL; + retval = SUCCESS; } - stmt->fetch.cls.ce = NULL; } else { - if (argc < 2 || argc > 3) { - goto fail_out; - } - convert_to_string_ex(args[skip+1]); - - if (FAILURE == zend_lookup_class(Z_STRVAL_PP(args[skip+1]), - Z_STRLEN_PP(args[skip+1]), &cep TSRMLS_CC)) { - goto fail_out; - } - - if (!cep || !*cep) { - goto fail_out; + if (argc < 2) { + pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode requires the classname argument" TSRMLS_CC); + } else if (argc > 3) { + pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "too many arguments" TSRMLS_CC); + } else if (Z_TYPE_PP(args[skip+1]) != IS_STRING) { + pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "classname must be a string" TSRMLS_CC); + } else { + retval = zend_lookup_class(Z_STRVAL_PP(args[skip+1]), + Z_STRLEN_PP(args[skip+1]), &cep TSRMLS_CC); + + if (SUCCESS == retval && cep && *cep) { + stmt->fetch.cls.ce = *cep; + } } - - stmt->fetch.cls.ce = *cep; } - stmt->fetch.cls.ctor_args = NULL; + if (SUCCESS == retval) { + stmt->fetch.cls.ctor_args = NULL; #ifdef ilia_0 /* we'll only need this when we have persistent statements, if ever */ - if (stmt->dbh->is_persistent) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP might crash if you don't call $stmt->setFetchMode() to reset to defaults on this persistent statement. This will be fixed in a later release"); - } + if (stmt->dbh->is_persistent) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP might crash if you don't call $stmt->setFetchMode() to reset to defaults on this persistent statement. This will be fixed in a later release"); + } #endif - if (argc == 3) { - if (Z_TYPE_PP(args[skip+2]) != IS_NULL && Z_TYPE_PP(args[skip+2]) != IS_ARRAY) { - pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "ctor_args must be either NULL or an array" TSRMLS_CC); - } else if (Z_TYPE_PP(args[skip+2]) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_PP(args[skip+2]))) { - ALLOC_ZVAL(stmt->fetch.cls.ctor_args); - *stmt->fetch.cls.ctor_args = **args[skip+2]; - zval_copy_ctor(stmt->fetch.cls.ctor_args); + if (argc == 3) { + if (Z_TYPE_PP(args[skip+2]) != IS_NULL && Z_TYPE_PP(args[skip+2]) != IS_ARRAY) { + pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "ctor_args must be either NULL or an array" TSRMLS_CC); + retval = FAILURE; + } else if (Z_TYPE_PP(args[skip+2]) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_PP(args[skip+2]))) { + ALLOC_ZVAL(stmt->fetch.cls.ctor_args); + *stmt->fetch.cls.ctor_args = **args[skip+2]; + zval_copy_ctor(stmt->fetch.cls.ctor_args); + } + } + + if (SUCCESS == retval) { + do_fetch_class_prepare(stmt TSRMLS_CC); } } - do_fetch_class_prepare(stmt TSRMLS_CC); break; case PDO_FETCH_INTO: if (argc != 2) { - goto fail_out; - } - if (Z_TYPE_PP(args[skip+1]) != IS_OBJECT) { - goto fail_out; + pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode requires the object parameter" TSRMLS_CC); + } else if (Z_TYPE_PP(args[skip+1]) != IS_OBJECT) { + pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "object must be an object" TSRMLS_CC); + } else { + retval = SUCCESS; } + + if (SUCCESS == retval) { #ifdef ilia_0 /* we'll only need this when we have persistent statements, if ever */ - if (stmt->dbh->is_persistent) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP might crash if you don't call $stmt->setFetchMode() to reset to defaults on this persistent statement. This will be fixed in a later release"); - } + if (stmt->dbh->is_persistent) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP might crash if you don't call $stmt->setFetchMode() to reset to defaults on this persistent statement. This will be fixed in a later release"); + } #endif - MAKE_STD_ZVAL(stmt->fetch.into); + MAKE_STD_ZVAL(stmt->fetch.into); - Z_TYPE_P(stmt->fetch.into) = IS_OBJECT; - Z_OBJ_HANDLE_P(stmt->fetch.into) = Z_OBJ_HANDLE_PP(args[skip+1]); - Z_OBJ_HT_P(stmt->fetch.into) = Z_OBJ_HT_PP(args[skip+1]); - zend_objects_store_add_ref(stmt->fetch.into TSRMLS_CC); + Z_TYPE_P(stmt->fetch.into) = IS_OBJECT; + Z_OBJ_HANDLE_P(stmt->fetch.into) = Z_OBJ_HANDLE_PP(args[skip+1]); + Z_OBJ_HT_P(stmt->fetch.into) = Z_OBJ_HT_PP(args[skip+1]); + zend_objects_store_add_ref(stmt->fetch.into TSRMLS_CC); + } + break; default: pdo_raise_impl_error(stmt->dbh, stmt, "22003", "Invalid fetch mode specified" TSRMLS_CC); - goto fail_out; } - stmt->default_fetch_type = mode; - efree(args); + if (SUCCESS == retval) { + stmt->default_fetch_type = mode; + } - return SUCCESS; + /* + * PDO error (if any) has already been raised at this point. + * + * The error_code is cleared, otherwise the caller will read the + * last error message from the driver. + * + */ + PDO_STMT_CLEAR_ERR(); + + efree(args); + + return retval; } static PHP_METHOD(PDOStatement, setFetchMode) http://cvs.php.net/viewvc.cgi/php-src/ext/pdo/tests/bug_44173.phpt?view=markup&rev=1.1 Index: php-src/ext/pdo/tests/bug_44173.phpt +++ php-src/ext/pdo/tests/bug_44173.phpt --TEST-- PDO Common: Bug #44173 (PDO->query() parameter parsing/checking needs an update) --SKIPIF-- <?php # vim:ft=php if (!extension_loaded('pdo')) die('skip'); $dir = getenv('REDIR_TEST_DIR'); if (false == $dir) die('skip no driver'); require_once $dir . 'pdo_test.inc'; PDOTest::skip(); ?> --FILE-- <?php if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.dirname(__FILE__) . '/../../pdo/tests/'); require getenv('REDIR_TEST_DIR') . 'pdo_test.inc'; $db = PDOTest::factory(); $db->exec("CREATE TABLE test (x int)"); $db->exec("INSERT INTO test VALUES (1)"); // Bug entry [1] $stmt = $db->query(); var_dump($stmt); // Bug entry [2] -- 1 is PDO::FETCH_LAZY $stmt = $db->query("SELECT * FROM test", PDO::FETCH_LAZY, 0, 0); var_dump($stmt); // Bug entry [3] $stmt = $db->query("SELECT * FROM test", 'abc'); var_dump($stmt); // Bug entry [4] $stmt = $db->query("SELECT * FROM test", PDO::FETCH_CLASS, 0, 0, 0); var_dump($stmt); // Bug entry [5] $stmt = $db->query("SELECT * FROM test", PDO::FETCH_INTO); var_dump($stmt); // Bug entry [6] $stmt = $db->query("SELECT * FROM test", PDO::FETCH_COLUMN); var_dump($stmt); // Bug entry [7] $stmt = $db->query("SELECT * FROM test", PDO::FETCH_CLASS); var_dump($stmt); ?> --EXPECTF-- Warning: PDO::query() expects at least 1 parameter, 0 given in %s bool(false) Warning: PDO::query(): SQLSTATE[HY000]: General error: fetch mode doesn't allow any extra arguments in %s bool(false) Warning: PDO::query(): SQLSTATE[HY000]: General error: mode must be an integer in %s bool(false) Warning: PDO::query(): SQLSTATE[HY000]: General error: too many arguments in %s bool(false) Warning: PDO::query(): SQLSTATE[HY000]: General error: fetch mode requires the object parameter in %s bool(false) Warning: PDO::query(): SQLSTATE[HY000]: General error: fetch mode requires the colno argument in %s bool(false) Warning: PDO::query(): SQLSTATE[HY000]: General error: fetch mode requires the classname argument in %s bool(false)
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php