mirror of
https://github.com/php/php-src.git
synced 2024-09-21 18:07:23 +00:00
Merge branch 'PHP-7.0'
* PHP-7.0: Fixed bug #71820 pg_fetch_object bind parameters before call constructor
This commit is contained in:
commit
ad7e1768aa
@ -1271,15 +1271,13 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
|
||||
zval dataset, retval;
|
||||
zend_fcall_info fci;
|
||||
zend_fcall_info_cache fcc;
|
||||
zend_bool props_handled = 0;
|
||||
|
||||
ZVAL_COPY_VALUE(&dataset, return_value);
|
||||
|
||||
object_and_properties_init(return_value, ce, NULL);
|
||||
if (!ce->default_properties_count && !ce->__set) {
|
||||
Z_OBJ_P(return_value)->properties = Z_ARR(dataset);
|
||||
} else {
|
||||
zend_merge_properties(return_value, Z_ARRVAL(dataset));
|
||||
zval_ptr_dtor(&dataset);
|
||||
props_handled = 1;
|
||||
}
|
||||
|
||||
if (ce->constructor) {
|
||||
@ -1300,6 +1298,9 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
|
||||
* single value is an array. Also we'd have to make that one
|
||||
* argument passed by reference.
|
||||
*/
|
||||
if (!props_handled) {
|
||||
zval_ptr_dtor(&dataset);
|
||||
}
|
||||
zend_throw_exception(zend_ce_exception, "Parameter ctor_params must be an array", 0);
|
||||
return;
|
||||
}
|
||||
@ -1312,7 +1313,14 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
|
||||
fcc.object = Z_OBJ_P(return_value);
|
||||
|
||||
if (zend_call_function(&fci, &fcc) == FAILURE) {
|
||||
if (fci.params) {
|
||||
efree(fci.params);
|
||||
}
|
||||
if (!props_handled) {
|
||||
zval_ptr_dtor(&dataset);
|
||||
}
|
||||
zend_throw_exception_ex(zend_ce_exception, 0, "Could not execute %s::%s()", ZSTR_VAL(ce->name), ZSTR_VAL(ce->constructor->common.function_name));
|
||||
return;
|
||||
} else {
|
||||
zval_ptr_dtor(&retval);
|
||||
}
|
||||
@ -1320,7 +1328,16 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
|
||||
efree(fci.params);
|
||||
}
|
||||
} else if (ctor_params) {
|
||||
if (!props_handled) {
|
||||
zval_ptr_dtor(&dataset);
|
||||
}
|
||||
zend_throw_exception_ex(zend_ce_exception, 0, "Class %s does not have a constructor hence you cannot use ctor_params", ZSTR_VAL(ce->name));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!props_handled) {
|
||||
zend_merge_properties(return_value, Z_ARRVAL(dataset));
|
||||
zval_ptr_dtor(&dataset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
104
ext/mysqli/tests/bug71820.phpt
Normal file
104
ext/mysqli/tests/bug71820.phpt
Normal file
@ -0,0 +1,104 @@
|
||||
--TEST--
|
||||
Bug #71820 __set has to be called after constructor, mysqli part
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require_once('skipif.inc');
|
||||
require_once('skipifconnectfailure.inc');
|
||||
require_once("connect.inc");
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
include "connect.inc";
|
||||
|
||||
$tableName = 'test_mysqli_fetch_object';
|
||||
|
||||
class TestRow
|
||||
{
|
||||
|
||||
private $set_from_constructor;
|
||||
private $data;
|
||||
private $hello = "world";
|
||||
|
||||
public function __construct($set_from_constructor)
|
||||
{
|
||||
$this->set_from_constructor = $set_from_constructor;
|
||||
}
|
||||
|
||||
public function __set($name, $value)
|
||||
{
|
||||
if (!isset($this->data[$name])) {
|
||||
/* $this->set_from_constructor has an expected value */
|
||||
$this->data[$name] = 42 == $this->set_from_constructor ? $value : -1;
|
||||
return;
|
||||
}
|
||||
throw new \Exception('Duplicity column name.');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (!($connection = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))) {
|
||||
printf("[001] Cannot connect to the server");
|
||||
}
|
||||
|
||||
$rc = mysqli_query($connection, "DROP TABLE IF EXISTS $tableName");
|
||||
if (!$rc)
|
||||
printf("[002] [%d] %s\n", mysqli_errno($connection), mysqli_error($connection));
|
||||
|
||||
$table = <<<SQL
|
||||
CREATE TABLE $tableName (
|
||||
id int NOT NULL auto_increment primary key,
|
||||
name varchar(255) NOT NULL
|
||||
);
|
||||
SQL;
|
||||
|
||||
$rc = mysqli_query($connection, $table);
|
||||
if (!$rc)
|
||||
printf("[003] [%d] %s\n", mysqli_errno($connection), mysqli_error($connection));
|
||||
|
||||
$rc = mysqli_query($connection, "INSERT INTO " . $tableName . " (name) VALUES ('Doe'), ('Joe')");
|
||||
if (!$rc)
|
||||
printf("[004] [%d] %s\n", mysqli_errno($connection), mysqli_error($connection));
|
||||
|
||||
$result = mysqli_query($connection, 'SELECT * FROM ' . $tableName . ' LIMIT 10');
|
||||
if (!$result)
|
||||
printf("[005] [%d] %s\n", mysqli_errno($result), mysqli_error($result));
|
||||
|
||||
|
||||
while ($row = mysqli_fetch_object($result, 'TestRow', [42])) {
|
||||
var_dump($row);
|
||||
}
|
||||
|
||||
mysqli_close($connection);
|
||||
|
||||
?>
|
||||
==DONE==
|
||||
--EXPECTF--
|
||||
object(TestRow)#%d (3) {
|
||||
["set_from_constructor":"TestRow":private]=>
|
||||
int(42)
|
||||
["data":"TestRow":private]=>
|
||||
array(2) {
|
||||
["id"]=>
|
||||
string(1) "1"
|
||||
["name"]=>
|
||||
string(3) "Doe"
|
||||
}
|
||||
["hello":"TestRow":private]=>
|
||||
string(5) "world"
|
||||
}
|
||||
object(TestRow)#%d (3) {
|
||||
["set_from_constructor":"TestRow":private]=>
|
||||
int(42)
|
||||
["data":"TestRow":private]=>
|
||||
array(2) {
|
||||
["id"]=>
|
||||
string(1) "2"
|
||||
["name"]=>
|
||||
string(3) "Joe"
|
||||
}
|
||||
["hello":"TestRow":private]=>
|
||||
string(5) "world"
|
||||
}
|
||||
==DONE==
|
@ -2812,14 +2812,13 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, zend_long result_
|
||||
zend_fcall_info fci;
|
||||
zend_fcall_info_cache fcc;
|
||||
zval retval;
|
||||
zend_bool props_handled = 0;
|
||||
|
||||
ZVAL_COPY_VALUE(&dataset, return_value);
|
||||
object_and_properties_init(return_value, ce, NULL);
|
||||
if (!ce->default_properties_count && !ce->__set) {
|
||||
Z_OBJ_P(return_value)->properties = Z_ARR(dataset);
|
||||
} else {
|
||||
zend_merge_properties(return_value, Z_ARRVAL(dataset));
|
||||
zval_ptr_dtor(&dataset);
|
||||
props_handled = 1;
|
||||
}
|
||||
|
||||
if (ce->constructor) {
|
||||
@ -2841,6 +2840,9 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, zend_long result_
|
||||
* argument passed by reference.
|
||||
*/
|
||||
zend_throw_exception(zend_ce_exception, "Parameter ctor_params must be an array", 0);
|
||||
if (!props_handled) {
|
||||
zval_ptr_dtor(&dataset);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2853,6 +2855,13 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, zend_long result_
|
||||
|
||||
if (zend_call_function(&fci, &fcc) == FAILURE) {
|
||||
zend_throw_exception_ex(zend_ce_exception, 0, "Could not execute %s::%s()", ce->name, ce->constructor->common.function_name);
|
||||
if (fci.params) {
|
||||
efree(fci.params);
|
||||
}
|
||||
if (!props_handled) {
|
||||
zval_ptr_dtor(&dataset);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
zval_ptr_dtor(&retval);
|
||||
}
|
||||
@ -2861,6 +2870,15 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, zend_long result_
|
||||
}
|
||||
} else if (ctor_params) {
|
||||
zend_throw_exception_ex(zend_ce_exception, 0, "Class %s does not have a constructor hence you cannot use ctor_params", ce->name);
|
||||
if (!props_handled) {
|
||||
zval_ptr_dtor(&dataset);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!props_handled) {
|
||||
zend_merge_properties(return_value, Z_ARRVAL(dataset));
|
||||
zval_ptr_dtor(&dataset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
93
ext/pgsql/tests/bug71820.phpt
Normal file
93
ext/pgsql/tests/bug71820.phpt
Normal file
@ -0,0 +1,93 @@
|
||||
--TEST--
|
||||
Bug #71820 pg_fetch_object bind parameters before call constructor
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require_once('skipif.inc');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once('config.inc');
|
||||
|
||||
$tableName = 'test_pg_fetch_object';
|
||||
|
||||
class TestRow
|
||||
{
|
||||
|
||||
private $set_from_constructor;
|
||||
private $data;
|
||||
private $hello = 42;
|
||||
|
||||
public function __construct($set_from_constructor)
|
||||
{
|
||||
$this->set_from_constructor = $set_from_constructor;
|
||||
}
|
||||
|
||||
public function __set($name, $value)
|
||||
{
|
||||
if (!isset($this->data[$name])) {
|
||||
/* $this->set_from_constructor has an expected value */
|
||||
$this->data[$name] = 42 == $this->set_from_constructor ? $value : -1;
|
||||
return;
|
||||
}
|
||||
throw new \Exception('Duplicity column name.');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$connection = pg_connect($conn_str);
|
||||
|
||||
if (!$connection) {
|
||||
die('Connection faild.');
|
||||
}
|
||||
|
||||
$table = <<<SQL
|
||||
CREATE TABLE IF NOT EXISTS $tableName (
|
||||
id serial NOT NULL,
|
||||
name character varying NOT NULL
|
||||
);
|
||||
SQL;
|
||||
pg_query($connection, $table);
|
||||
|
||||
pg_query_params('INSERT INTO ' . $tableName . ' (name) VALUES ($1), ($2);', ['$1' => 'Doe', '$2' => 'Joe']);
|
||||
|
||||
$result = pg_query('SELECT * FROM ' . $tableName . ' LIMIT 10;');
|
||||
|
||||
while ($row = pg_fetch_object($result, NULL, 'TestRow', [42])) {
|
||||
var_dump($row);
|
||||
}
|
||||
|
||||
pg_query($connection, "DROP TABLE $tableName");
|
||||
|
||||
pg_close($connection);
|
||||
|
||||
?>
|
||||
==DONE==
|
||||
--EXPECTF--
|
||||
object(TestRow)#%d (3) {
|
||||
["set_from_constructor":"TestRow":private]=>
|
||||
int(42)
|
||||
["data":"TestRow":private]=>
|
||||
array(2) {
|
||||
["id"]=>
|
||||
string(1) "1"
|
||||
["name"]=>
|
||||
string(3) "Doe"
|
||||
}
|
||||
["hello":"TestRow":private]=>
|
||||
int(42)
|
||||
}
|
||||
object(TestRow)#%d (3) {
|
||||
["set_from_constructor":"TestRow":private]=>
|
||||
int(42)
|
||||
["data":"TestRow":private]=>
|
||||
array(2) {
|
||||
["id"]=>
|
||||
string(1) "2"
|
||||
["name"]=>
|
||||
string(3) "Joe"
|
||||
}
|
||||
["hello":"TestRow":private]=>
|
||||
int(42)
|
||||
}
|
||||
==DONE==
|
Loading…
Reference in New Issue
Block a user