Skip to content

Commit

Permalink
Backport patch for bug #71820
Browse files Browse the repository at this point in the history
  • Loading branch information
weltling committed Mar 17, 2016
1 parent eb40562 commit 1b632cf
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 2 deletions.
15 changes: 14 additions & 1 deletion ext/mysqli/mysqli.c
Original file line number Diff line number Diff line change
Expand Up @@ -1295,9 +1295,13 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
zend_fcall_info fci;
zend_fcall_info_cache fcc;
zval *retval_ptr;
zend_bool props_merged = 0;

object_and_properties_init(return_value, ce, NULL);
zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC);
if (!ce->__set) {
props_merged = 1;
zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC);
}

if (ce->constructor) {
fci.size = sizeof(fci);
Expand Down Expand Up @@ -1331,6 +1335,10 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags

if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Could not execute %s::%s()", ce->name, ce->constructor->common.function_name);
if (fci.params) {
efree(fci.params);
}
return;
} else {
if (retval_ptr) {
zval_ptr_dtor(&retval_ptr);
Expand All @@ -1341,6 +1349,11 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
}
} else if (ctor_params) {
zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Class %s does not have a constructor hence you cannot use ctor_params", ce->name);
return;
}

if (!props_merged) {
zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC);
}
}
}
Expand Down
104 changes: 104 additions & 0 deletions ext/mysqli/tests/bug71820.phpt
Original file line number Diff line number Diff line change
@@ -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==
15 changes: 14 additions & 1 deletion ext/pgsql/pgsql.c
Original file line number Diff line number Diff line change
Expand Up @@ -2784,9 +2784,13 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, long result_type,
zend_fcall_info fci;
zend_fcall_info_cache fcc;
zval *retval_ptr;
zend_bool props_merged = 0;

object_and_properties_init(return_value, ce, NULL);
zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC);
if (!ce->__set) {
props_merged = 1;
zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC);
}

if (ce->constructor) {
fci.size = sizeof(fci);
Expand Down Expand Up @@ -2820,6 +2824,10 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, long result_type,

if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Could not execute %s::%s()", ce->name, ce->constructor->common.function_name);
if (fci.params) {
efree(fci.params);
}
return;
} else {
if (retval_ptr) {
zval_ptr_dtor(&retval_ptr);
Expand All @@ -2830,6 +2838,11 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, long result_type,
}
} else if (ctor_params) {
zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Class %s does not have a constructor hence you cannot use ctor_params", ce->name);
return;
}

if (!props_merged) {
zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC);
}
}
}
Expand Down
93 changes: 93 additions & 0 deletions ext/pgsql/tests/bug71820.phpt
Original file line number Diff line number Diff line change
@@ -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==

0 comments on commit 1b632cf

Please sign in to comment.