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

Reply via email to