From 251ed3ef39338ce6cafc5013974991d04a50ce93 Mon Sep 17 00:00:00 2001 From: Hannes Magnusson Date: Tue, 14 Apr 2015 10:55:06 -0700 Subject: [PATCH] PHPC-239: Cursor refcount issues This also fixes re-iterating over a cursor where we would not free the firstBatch properly, so the last result was still there. --- php_phongo.c | 9 ++- tests/standalone/bug0239.phpt | 133 ++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 tests/standalone/bug0239.phpt diff --git a/php_phongo.c b/php_phongo.c index c26eb7b8d..ec0d58d3d 100644 --- a/php_phongo.c +++ b/php_phongo.c @@ -1561,13 +1561,18 @@ static void php_phongo_cursor_iterator_dtor(zend_object_iterator *iter TSRMLS_DC { php_phongo_cursor_iterator *cursor_it = (php_phongo_cursor_iterator *)iter; + if (cursor_it->cursor->firstBatch) { + bson_clear(&cursor_it->cursor->firstBatch); + cursor_it->cursor->firstBatch = NULL; + } + + php_phongo_cursor_free_current(cursor_it->cursor); + if (cursor_it->intern.data) { zval_ptr_dtor((zval**)&cursor_it->intern.data); cursor_it->intern.data = NULL; } - php_phongo_cursor_free_current(cursor_it->cursor); - efree(cursor_it); } /* }}} */ diff --git a/tests/standalone/bug0239.phpt b/tests/standalone/bug0239.phpt new file mode 100644 index 000000000..335f0b3ed --- /dev/null +++ b/tests/standalone/bug0239.phpt @@ -0,0 +1,133 @@ +--TEST-- +PHPC-239: Iterator segfault +--SKIPIF-- + +--FILE-- +streetAddress = $streetAddress; + $this->city = $city; + $this->postalCode = $postalCode; + + } + function bsonUnserialize(array $array) { + foreach($array as $k => $v) { + $this->{$k} = $v; + } + + return $this; + } + + function bsonSerialize() { + return get_object_vars($this); + } +} + +class Person implements BSON\Persistable { + protected $_id; + protected $username; + protected $email; + protected $name; + protected $addresses = array(); + + function __construct($username, $email, $name) { + $this->username = $username; + $this->email = $email; + $this->name = $name; + + /* Pregenerate our ObjectID */ + $this->_id = new BSON\ObjectID(); + } + function addAddress(Address $address) { + $this->addresses[] = $address; + } + + function bsonUnserialize(array $array) { + foreach($array as $k => $v) { + $this->{$k} = $v; + } + } + + function bsonSerialize() { + return get_object_vars($this); + } + + function getName() { + return $this->name; + } +} + + +$bulk = new MongoDB\Driver\BulkWrite; + + +$lair77 = new Person('lair77', 'claire77@example.net', 'Claire Corwin'); +$hillardhaven = new Address('4527 Kohler Square Apt. 316', 'Hillardhaven', '02622-5175'); +$lair77->addAddress($hillardhaven); +$prudencemouth = new Address('7042 Freida Springs', 'Prudencemouth', '94805'); +$lair77->addAddress($prudencemouth); +$bulk->insert($lair77); + + + +$hartmann = new Person('hartmann', 'hartmann@example.org', 'Hartmann Dedrick'); +$leannefurt = new Address('151 Delbert Hills Suite 923', 'Leannefurt', '22036'); +$hartmann->addAddress($leannefurt); +$bulk->insert($hartmann); + + +$dropcoll = new MongoDB\Driver\Command(array("drop" => COLLECTION_NAME)); +$query = new MongoDB\Driver\Query(array()); +$queryHartmann = new MongoDB\Driver\Query(array("username" => "hartmann")); + + + +$m = new MongoDB\Driver\Manager(STANDALONE); +try { + $m->executeCommand(DATABASE_NAME, $dropcoll); +} catch(Exception $e) {} + +$m->executeBulkWrite(NS, $bulk); + + +$res = $m->executeQuery(NS, $query); +foreach($res as $person) { + var_dump($person->getName()); +} +foreach($res as $person) { + echo "This will never happen: "; + echo $person->getName(), "\n"; +} + +echo "-----\n"; +$cursor = $m->executeQuery(NS, $queryHartmann); +foreach($cursor as $hartmann) { + echo $hartmann->getName(), "\n"; +} + +foreach($cursor as $hartmann) { + echo "This will never happen: "; + echo $hartmann->getName(), "\n"; +} +foreach($cursor as $hartmann) { + echo "This will never happen: "; + echo $hartmann->getName(), "\n"; +} +echo "All Good!\n"; +?> +===DONE=== + +--EXPECT-- +string(13) "Claire Corwin" +string(16) "Hartmann Dedrick" +----- +Hartmann Dedrick +All Good! +===DONE===