@@ -1717,27 +1717,24 @@ bool pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, uint32_t mode_a
17171717 uint32_t arg1_arg_num = mode_arg_num + 1 ;
17181718 uint32_t constructor_arg_num = mode_arg_num + 2 ;
17191719 uint32_t total_num_args = mode_arg_num + variadic_num_args ;
1720+ zend_long fetch_type = mode & ~PDO_FETCH_FLAGS ;
1721+ zend_long fetch_column = 0 ;
1722+ zend_class_entry * fetch_class = NULL ;
1723+ zend_array * fetch_ctor_args = NULL ;
1724+ zend_object * fetch_into = NULL ;
1725+ zval old_ctor_args ;
1726+ zval old_into ;
17201727
1721- switch (stmt -> default_fetch_type ) {
1722- case PDO_FETCH_INTO :
1723- if (!Z_ISUNDEF (stmt -> fetch .into )) {
1724- zval_ptr_dtor (& stmt -> fetch .into );
1725- ZVAL_UNDEF (& stmt -> fetch .into );
1726- }
1727- break ;
1728- default :
1729- ;
1730- }
1731-
1732- stmt -> default_fetch_type = PDO_FETCH_BOTH ;
1728+ ZVAL_UNDEF (& old_ctor_args );
1729+ ZVAL_UNDEF (& old_into );
17331730
17341731 flags = mode & PDO_FETCH_FLAGS ;
17351732
17361733 if (!pdo_stmt_verify_mode (stmt , mode , mode_arg_num , false)) {
17371734 return false;
17381735 }
17391736
1740- switch (mode & ~ PDO_FETCH_FLAGS ) {
1737+ switch (fetch_type ) {
17411738 case PDO_FETCH_USE_DEFAULT :
17421739 case PDO_FETCH_LAZY :
17431740 case PDO_FETCH_ASSOC :
@@ -1772,13 +1769,11 @@ bool pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, uint32_t mode_a
17721769 zend_argument_value_error (arg1_arg_num , "must be greater than or equal to 0" );
17731770 return false;
17741771 }
1775- stmt -> fetch . column = Z_LVAL (args [0 ]);
1772+ fetch_column = Z_LVAL (args [0 ]);
17761773 break ;
17771774
17781775 case PDO_FETCH_CLASS : {
17791776 HashTable * constructor_args = NULL ;
1780- /* Undef constructor arguments */
1781- ZVAL_UNDEF (& stmt -> fetch .cls .ctor_args );
17821777 /* Gets its class name from 1st column */
17831778 if ((flags & PDO_FETCH_CLASSTYPE ) == PDO_FETCH_CLASSTYPE ) {
17841779 if (variadic_num_args != 0 ) {
@@ -1788,7 +1783,6 @@ bool pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, uint32_t mode_a
17881783 zend_string_release (func );
17891784 return false;
17901785 }
1791- stmt -> fetch .cls .ce = NULL ;
17921786 } else {
17931787 zend_class_entry * cep ;
17941788 if (variadic_num_args == 0 ) {
@@ -1827,15 +1821,17 @@ bool pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, uint32_t mode_a
18271821 constructor_args = Z_ARRVAL (args [1 ]);
18281822 }
18291823 }
1830- stmt -> fetch . cls . ce = cep ;
1824+ fetch_class = cep ;
18311825
18321826 /* If constructor arguments are present and not empty */
18331827 if (constructor_args ) {
1834- ZVAL_ARR (& stmt -> fetch .cls .ctor_args , zend_array_dup (constructor_args ));
1828+ if (!cep -> constructor ) {
1829+ zend_throw_error (NULL , "User-supplied statement does not accept constructor arguments" );
1830+ return false;
1831+ }
1832+ fetch_ctor_args = zend_array_dup (constructor_args );
18351833 }
18361834 }
1837-
1838- do_fetch_class_prepare (stmt );
18391835 break ;
18401836 }
18411837 case PDO_FETCH_INTO :
@@ -1851,15 +1847,53 @@ bool pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, uint32_t mode_a
18511847 return false;
18521848 }
18531849
1854- ZVAL_COPY ( & stmt -> fetch . into , & args [0 ]);
1850+ fetch_into = Z_OBJ ( args [0 ]);
18551851 break ;
18561852 default :
18571853 zend_argument_value_error (mode_arg_num , "must be one of the PDO::FETCH_* constants" );
18581854 return false;
18591855 }
18601856
1857+ if ((stmt -> default_fetch_type & ~PDO_FETCH_FLAGS ) == PDO_FETCH_INTO ) {
1858+ ZVAL_COPY_VALUE (& old_into , & stmt -> fetch .into );
1859+ ZVAL_UNDEF (& stmt -> fetch .into );
1860+ } else if ((stmt -> default_fetch_type & ~PDO_FETCH_FLAGS ) == PDO_FETCH_CLASS ) {
1861+ do_fetch_opt_finish (stmt , 0 );
1862+ ZVAL_COPY_VALUE (& old_ctor_args , & stmt -> fetch .cls .ctor_args );
1863+ ZVAL_UNDEF (& stmt -> fetch .cls .ctor_args );
1864+ } else {
1865+ do_fetch_opt_finish (stmt , 1 );
1866+ }
1867+
1868+ switch (fetch_type ) {
1869+ case PDO_FETCH_COLUMN :
1870+ stmt -> fetch .column = fetch_column ;
1871+ break ;
1872+ case PDO_FETCH_CLASS :
1873+ stmt -> fetch .cls .ce = fetch_class ;
1874+ if (fetch_ctor_args ) {
1875+ ZVAL_ARR (& stmt -> fetch .cls .ctor_args , fetch_ctor_args );
1876+ } else {
1877+ ZVAL_UNDEF (& stmt -> fetch .cls .ctor_args );
1878+ }
1879+ do_fetch_class_prepare (stmt );
1880+ break ;
1881+ case PDO_FETCH_INTO :
1882+ ZVAL_OBJ_COPY (& stmt -> fetch .into , fetch_into );
1883+ break ;
1884+ default :
1885+ break ;
1886+ }
1887+
18611888 stmt -> default_fetch_type = mode ;
18621889
1890+ if (!Z_ISUNDEF (old_into )) {
1891+ zval_ptr_dtor (& old_into );
1892+ }
1893+ if (!Z_ISUNDEF (old_ctor_args )) {
1894+ zval_ptr_dtor (& old_ctor_args );
1895+ }
1896+
18631897 return true;
18641898}
18651899
@@ -1875,8 +1909,6 @@ PHP_METHOD(PDOStatement, setFetchMode)
18751909
18761910 PHP_STMT_GET_OBJ ;
18771911
1878- do_fetch_opt_finish (stmt , 1 );
1879-
18801912 if (!pdo_stmt_setup_fetch_mode (stmt , fetch_mode , 1 , args , num_args )) {
18811913 RETURN_THROWS ();
18821914 }
0 commit comments