From 7c3bd45b8254758e9016f1f15d7dc02c5de1b067 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sun, 15 Nov 2009 16:20:37 +0000 Subject: [PATCH] - Fixed bug #49521 (PDO fetchObject sets values before calling constructor) (patch by Pierrick) --- ext/pdo/pdo_stmt.c | 47 ++++++++++--------- ext/pdo/tests/pdo_005.phpt | 8 ++-- .../tests/pdo_mysql_stmt_fetchobject.phpt | 8 ++-- ext/pdo_sqlite/tests/bug49521.phpt | 39 +++++++++++++++ 4 files changed, 73 insertions(+), 29 deletions(-) create mode 100644 ext/pdo_sqlite/tests/bug49521.phpt diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 1e443c2246..0ab02319b7 100755 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -1107,6 +1107,32 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value, } } + switch (how) { + case PDO_FETCH_CLASS: + if (ce->constructor && !(flags & (PDO_FETCH_PROPS_LATE | PDO_FETCH_SERIALIZE))) { + stmt->fetch.cls.fci.object_ptr = return_value; + stmt->fetch.cls.fcc.object_ptr = return_value; + if (zend_call_function(&stmt->fetch.cls.fci, &stmt->fetch.cls.fcc TSRMLS_CC) == FAILURE) { + pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "could not call class constructor" TSRMLS_CC); + return 0; + } else { + if (stmt->fetch.cls.retval_ptr) { + zval_ptr_dtor(&stmt->fetch.cls.retval_ptr); + } + } + } + if (flags & PDO_FETCH_CLASSTYPE) { + do_fetch_opt_finish(stmt, 0 TSRMLS_CC); + stmt->fetch.cls.ce = old_ce; + stmt->fetch.cls.ctor_args = old_ctor_args; + stmt->fetch.cls.fci.param_count = old_arg_count; + } + break; + + default: + break; + } + for (idx = 0; i < stmt->column_count; i++, idx++) { zval *val; MAKE_STD_ZVAL(val); @@ -1245,27 +1271,6 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value, } switch (how) { - case PDO_FETCH_CLASS: - if (ce->constructor && !(flags & (PDO_FETCH_PROPS_LATE | PDO_FETCH_SERIALIZE))) { - stmt->fetch.cls.fci.object_ptr = return_value; - stmt->fetch.cls.fcc.object_ptr = return_value; - if (zend_call_function(&stmt->fetch.cls.fci, &stmt->fetch.cls.fcc TSRMLS_CC) == FAILURE) { - pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "could not call class constructor" TSRMLS_CC); - return 0; - } else { - if (stmt->fetch.cls.retval_ptr) { - zval_ptr_dtor(&stmt->fetch.cls.retval_ptr); - } - } - } - if (flags & PDO_FETCH_CLASSTYPE) { - do_fetch_opt_finish(stmt, 0 TSRMLS_CC); - stmt->fetch.cls.ce = old_ce; - stmt->fetch.cls.ctor_args = old_ctor_args; - stmt->fetch.cls.fci.param_count = old_arg_count; - } - break; - case PDO_FETCH_FUNC: stmt->fetch.func.fci.param_count = idx; stmt->fetch.func.fci.retval_ptr_ptr = &retval; diff --git a/ext/pdo/tests/pdo_005.phpt b/ext/pdo/tests/pdo_005.phpt index 06421a1ccb..4eac938aa8 100644 --- a/ext/pdo/tests/pdo_005.phpt +++ b/ext/pdo/tests/pdo_005.phpt @@ -34,7 +34,7 @@ class TestDerived extends TestBase public function __construct(&$row) { - echo __METHOD__ . "($row,{$this->id})\n"; + echo __METHOD__ . "($row)\n"; $this->row = $row++; } } @@ -108,9 +108,9 @@ array(3) { unicode(2) "CC" } } -TestDerived::__construct(0,1) -TestDerived::__construct(1,2) -TestDerived::__construct(2,3) +TestDerived::__construct(0) +TestDerived::__construct(1) +TestDerived::__construct(2) array(3) { [0]=> object(TestDerived)#%d (5) { diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_fetchobject.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_fetchobject.phpt index 067f9ca704..672094cd2a 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_fetchobject.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_fetchobject.phpt @@ -71,21 +71,21 @@ require dirname(__FILE__) . '/mysql_pdo_test.inc'; MySQLPDOTest::dropTestTable(); ?> --EXPECTF-- +myclass::__construct(0, 1): 0 / 0 myclass::__set(id, -'1'-) 1 myclass::__set(, -''-) 2 myclass::__set(null, -NULL-) 3 myclass::__set(, -''-) 4 -myclass::__construct(0, 1): 4 / 4 +myclass::__construct(1, 2): 4 / 0 myclass::__set(id, -'2'-) 1 myclass::__set(, -''-) 2 myclass::__set(null, -NULL-) 3 myclass::__set(, -''-) 4 -myclass::__construct(1, 2): 8 / 4 +myclass::__construct(2, 3): 8 / 0 myclass::__set(id, -'3'-) 1 myclass::__set(, -''-) 2 myclass::__set(null, -NULL-) 3 myclass::__set(, -''-) 4 -myclass::__construct(2, 3): 12 / 4 object(myclass)#%d (4) { [%u|b%"set_calls":"myclass":private]=> int(4) @@ -96,4 +96,4 @@ object(myclass)#%d (4) { [%u|b%"null"]=> NULL } -done! \ No newline at end of file +done! diff --git a/ext/pdo_sqlite/tests/bug49521.phpt b/ext/pdo_sqlite/tests/bug49521.phpt new file mode 100644 index 0000000000..26cd2b2171 --- /dev/null +++ b/ext/pdo_sqlite/tests/bug49521.phpt @@ -0,0 +1,39 @@ +--TEST-- +Bug #49521 (PDO fetchObject sets values before calling constructor) +--SKIPIF-- + +--FILE-- +title = ''; + echo __METHOD__,"\n"; + } + public function __set($a, $b) { + echo __METHOD__,"\n"; + var_dump($a); + } +} + +$pdo = new PDO('sqlite::memory:'); +$pdo->exec('CREATE TABLE book(title,author)'); +$pdo->exec('INSERT INTO book VALUES ("PHP","Rasmus")'); +$statement = $pdo->prepare('SELECT * FROM book WHERE title="PHP"'); +$statement->execute(); +var_dump($statement->fetchObject('Book', array(1))); + +?> +--EXPECTF-- +Book::__construct +object(Book)#%d (2) { + [%u|b%"title"]=> + string(3) "PHP" + [%u|b%"author"]=> + string(6) "Rasmus" +} -- 2.50.1