Skip to content

Commit b0519cb

Browse files
committed
Merge pull request #44 from jmikola/phpc-255
PHPC-255 and PHPC-282: Do not allow multiple Cursor iterators or rewinds
2 parents fdc71b4 + 04d589b commit b0519cb

13 files changed

+321
-275
lines changed

config.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ if test "$MONGODB" != "no"; then
165165
";
166166
MONGODB_MONGODB_EXCEPTIONS="\
167167
src/MongoDB/Exception/Exception.c \
168+
src/MongoDB/Exception/LogicException.c \
168169
src/MongoDB/Exception/RuntimeException.c \
169170
src/MongoDB/Exception/UnexpectedValueException.c \
170171
src/MongoDB/Exception/InvalidArgumentException.c \

config.w32

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ if (PHP_MONGODB != "no") {
1010
ADD_SOURCES(configure_module_dirname + "/src", "bson.c", "mongodb");
1111
ADD_SOURCES(configure_module_dirname + "/src/BSON", "Type.c Unserializable.c Serializable.c Persistable.c Binary.c Javascript.c MaxKey.c MinKey.c ObjectID.c Regex.c Timestamp.c UTCDatetime.c", "mongodb");
1212
ADD_SOURCES(configure_module_dirname + "/src/MongoDB", "Command.c Cursor.c CursorId.c Manager.c Query.c ReadPreference.c Server.c BulkWrite.c WriteConcern.c WriteConcernError.c WriteError.c WriteResult.c", "mongodb");
13-
ADD_SOURCES(configure_module_dirname + "/src/MongoDB/Exception", "Exception.c RuntimeException.c UnexpectedValueException.c InvalidArgumentException.c ConnectionException.c AuthenticationException.c SSLConnectionException.c DuplicateKeyException.c ExecutionTimeoutException.c ConnectionTimeoutException.c WriteException.c WriteConcernException.c BulkWriteException.c", "mongodb");
13+
ADD_SOURCES(configure_module_dirname + "/src/MongoDB/Exception", "Exception.c LogicException.c RuntimeException.c UnexpectedValueException.c InvalidArgumentException.c ConnectionException.c AuthenticationException.c SSLConnectionException.c DuplicateKeyException.c ExecutionTimeoutException.c ConnectionTimeoutException.c WriteException.c WriteConcernException.c BulkWriteException.c", "mongodb");
1414
ADD_SOURCES(configure_module_dirname + "/src/contrib/", "php-ssl.c", "mongodb");
1515
ADD_SOURCES(configure_module_dirname + "/src/libbson/src/yajl", "yajl_version.c yajl.c yajl_encode.c yajl_lex.c yajl_parser.c yajl_buf.c yajl_tree.c yajl_alloc.c yajl_gen.c", "mongodb");
1616
ADD_SOURCES(configure_module_dirname + "/src/libbson/src/bson", "bcon.c bson.c bson-atomic.c bson-clock.c bson-context.c bson-error.c bson-iter.c bson-iso8601.c bson-json.c bson-keys.c bson-md5.c bson-memory.c bson-oid.c bson-reader.c bson-string.c bson-timegm.c bson-utf8.c bson-value.c bson-version.c bson-writer.c", "mongodb");

php_phongo.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ zend_class_entry* phongo_exception_from_phongo_domain(php_phongo_error_domain_t
8383
switch (domain) {
8484
case PHONGO_ERROR_INVALID_ARGUMENT:
8585
return php_phongo_invalidargumentexception_ce;
86+
case PHONGO_ERROR_LOGIC:
87+
return php_phongo_logicexception_ce;
8688
case PHONGO_ERROR_RUNTIME:
8789
return php_phongo_runtimeexception_ce;
8890
case PHONGO_ERROR_UNEXPECTED_VALUE:
@@ -1671,6 +1673,11 @@ static void php_phongo_cursor_iterator_rewind(zend_object_iterator *iter TSRMLS_
16711673
php_phongo_cursor_t *cursor = cursor_it->cursor;
16721674
const bson_t *doc;
16731675

1676+
if (cursor_it->current > 0) {
1677+
phongo_throw_exception(PHONGO_ERROR_LOGIC TSRMLS_CC, "Cursors cannot rewind after starting iteration");
1678+
return;
1679+
}
1680+
16741681
php_phongo_cursor_free_current(cursor);
16751682

16761683
doc = mongoc_cursor_current(cursor->cursor);
@@ -1694,18 +1701,26 @@ zend_object_iterator_funcs php_phongo_cursor_iterator_funcs = {
16941701

16951702
zend_object_iterator *php_phongo_cursor_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
16961703
{
1704+
php_phongo_cursor_t *cursor = zend_object_store_get_object(object TSRMLS_CC);
16971705
php_phongo_cursor_iterator *cursor_it = NULL;
16981706

16991707
if (by_ref) {
17001708
zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
17011709
}
17021710

1711+
if (cursor->got_iterator) {
1712+
phongo_throw_exception(PHONGO_ERROR_LOGIC TSRMLS_CC, "Cursors cannot yield multiple iterators");
1713+
return NULL;
1714+
}
1715+
1716+
cursor->got_iterator = 1;
1717+
17031718
cursor_it = ecalloc(1, sizeof(php_phongo_cursor_iterator));
17041719

17051720
Z_ADDREF_P(object);
17061721
cursor_it->intern.data = (void*)object;
17071722
cursor_it->intern.funcs = &php_phongo_cursor_iterator_funcs;
1708-
cursor_it->cursor = (php_phongo_cursor_t *)zend_object_store_get_object(object TSRMLS_CC);
1723+
cursor_it->cursor = cursor;
17091724
/* cursor_it->current should already be allocated to zero */
17101725

17111726
php_phongo_cursor_free_current(cursor_it->cursor);
@@ -1818,6 +1833,7 @@ PHP_MINIT_FUNCTION(mongodb)
18181833
PHP_MINIT(WriteResult)(INIT_FUNC_ARGS_PASSTHRU);
18191834

18201835
PHP_MINIT(Exception)(INIT_FUNC_ARGS_PASSTHRU);
1836+
PHP_MINIT(LogicException)(INIT_FUNC_ARGS_PASSTHRU);
18211837
PHP_MINIT(RuntimeException)(INIT_FUNC_ARGS_PASSTHRU);
18221838
PHP_MINIT(UnexpectedValueException)(INIT_FUNC_ARGS_PASSTHRU);
18231839
PHP_MINIT(InvalidArgumentException)(INIT_FUNC_ARGS_PASSTHRU);

php_phongo.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ typedef enum {
7272
PHONGO_ERROR_WRITE_SINGLE_FAILED = 4,
7373
PHONGO_ERROR_WRITE_FAILED = 5,
7474
PHONGO_ERROR_WRITECONCERN_FAILED = 6,
75-
PHONGO_ERROR_CONNECTION_FAILED = 7
75+
PHONGO_ERROR_CONNECTION_FAILED = 7,
76+
PHONGO_ERROR_LOGIC = 9
7677
} php_phongo_error_domain_t;
7778

7879
typedef struct

php_phongo_classes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ typedef struct {
4040
mongoc_client_t *client;
4141
int server_id;
4242
php_phongo_bson_state visitor_data;
43+
int got_iterator;
4344
} php_phongo_cursor_t;
4445

4546
typedef struct {
@@ -175,6 +176,7 @@ extern PHONGO_API zend_class_entry *php_phongo_writeerror_ce;
175176
extern PHONGO_API zend_class_entry *php_phongo_writeresult_ce;
176177

177178
extern PHONGO_API zend_class_entry *php_phongo_exception_ce;
179+
extern PHONGO_API zend_class_entry *php_phongo_logicexception_ce;
178180
extern PHONGO_API zend_class_entry *php_phongo_runtimeexception_ce;
179181
extern PHONGO_API zend_class_entry *php_phongo_unexpectedvalueexception_ce;
180182
extern PHONGO_API zend_class_entry *php_phongo_invalidargumentexception_ce;
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
+---------------------------------------------------------------------------+
3+
| PHP Driver for MongoDB |
4+
+---------------------------------------------------------------------------+
5+
| Copyright 2013-2015 MongoDB, Inc. |
6+
| |
7+
| Licensed under the Apache License, Version 2.0 (the "License"); |
8+
| you may not use this file except in compliance with the License. |
9+
| You may obtain a copy of the License at |
10+
| |
11+
| http://www.apache.org/licenses/LICENSE-2.0 |
12+
| |
13+
| Unless required by applicable law or agreed to in writing, software |
14+
| distributed under the License is distributed on an "AS IS" BASIS, |
15+
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16+
| See the License for the specific language governing permissions and |
17+
| limitations under the License. |
18+
+---------------------------------------------------------------------------+
19+
| Copyright (c) 2014-2015 MongoDB, Inc. |
20+
+---------------------------------------------------------------------------+
21+
*/
22+
23+
#ifdef HAVE_CONFIG_H
24+
# include "config.h"
25+
#endif
26+
27+
/* External libs */
28+
#include <bson.h>
29+
#include <mongoc.h>
30+
31+
/* PHP Core stuff */
32+
#include <php.h>
33+
#include <php_ini.h>
34+
#include <ext/standard/info.h>
35+
#include <Zend/zend_interfaces.h>
36+
#include <ext/spl/spl_iterators.h>
37+
/* Our Compatability header */
38+
#include "phongo_compat.h"
39+
40+
/* Our stuffz */
41+
#include "php_phongo.h"
42+
#include "php_bson.h"
43+
#include <ext/spl/spl_exceptions.h>
44+
45+
46+
PHONGO_API zend_class_entry *php_phongo_logicexception_ce;
47+
48+
/* {{{ MongoDB\Driver\LogicException */
49+
50+
static zend_function_entry php_phongo_logicexception_me[] = {
51+
PHP_FE_END
52+
};
53+
54+
/* }}} */
55+
56+
57+
/* {{{ PHP_MINIT_FUNCTION */
58+
PHP_MINIT_FUNCTION(LogicException)
59+
{
60+
zend_class_entry ce;
61+
(void)type;(void)module_number;
62+
63+
INIT_NS_CLASS_ENTRY(ce, "MongoDB\\Driver\\Exception", "LogicException", php_phongo_logicexception_me);
64+
php_phongo_logicexception_ce = zend_register_internal_class_ex(&ce, spl_ce_LogicException, NULL TSRMLS_CC);
65+
zend_class_implements(php_phongo_logicexception_ce TSRMLS_CC, 1, php_phongo_exception_ce);
66+
67+
return SUCCESS;
68+
}
69+
/* }}} */
70+
71+
72+
73+
/*
74+
* Local variables:
75+
* tab-width: 4
76+
* c-basic-offset: 4
77+
* End:
78+
* vim600: noet sw=4 ts=4 fdm=marker
79+
* vim<600: noet sw=4 ts=4
80+
*/

tests/standalone/bug0239.phpt

Lines changed: 0 additions & 133 deletions
This file was deleted.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
--TEST--
2+
MongoDB\Driver\Cursor get_iterator handler does not yield multiple iterators (foreach)
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; CLEANUP(STANDALONE) ?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
$manager = new MongoDB\Driver\Manager(STANDALONE);
10+
11+
$bulkWrite = new MongoDB\Driver\BulkWrite;
12+
13+
for ($i = 0; $i < 3; $i++) {
14+
$bulkWrite->insert(array('_id' => $i));
15+
}
16+
17+
$writeResult = $manager->executeBulkWrite(NS, $bulkWrite);
18+
printf("Inserted: %d\n", $writeResult->getInsertedCount());
19+
20+
$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query(array()));
21+
22+
echo "\nFirst foreach statement:\n";
23+
24+
foreach ($cursor as $document) {
25+
var_dump($document);
26+
}
27+
28+
echo "\nSecond foreach statement:\n";
29+
30+
try {
31+
foreach ($cursor as $document) {
32+
echo "FAILED: get_iterator should not yield multiple iterators\n";
33+
}
34+
} catch (MongoDB\Driver\Exception\LogicException $e) {
35+
printf("LogicException: %s\n", $e->getMessage());
36+
}
37+
38+
?>
39+
===DONE===
40+
<?php exit(0); ?>
41+
--EXPECT--
42+
Inserted: 3
43+
44+
First foreach statement:
45+
array(1) {
46+
["_id"]=>
47+
int(0)
48+
}
49+
array(1) {
50+
["_id"]=>
51+
int(1)
52+
}
53+
array(1) {
54+
["_id"]=>
55+
int(2)
56+
}
57+
58+
Second foreach statement:
59+
LogicException: Cursors cannot yield multiple iterators
60+
===DONE===

0 commit comments

Comments
 (0)