File tree Expand file tree Collapse file tree 2 files changed +56
-0
lines changed
Expand file tree Collapse file tree 2 files changed +56
-0
lines changed Original file line number Diff line number Diff line change @@ -227,9 +227,23 @@ PHP_METHOD(Cursor, setTypeMap)
227227 return ;
228228 }
229229
230+ /* Check if the existing element needs to be freed before we overwrite
231+ * visitor_data, which contains the only reference to it. */
232+ if (!Z_ISUNDEF (intern -> visitor_data .zchild )) {
233+ php_phongo_cursor_free_current (intern );
234+ }
235+
230236 phongo_bson_typemap_to_state (typemap , & state .map TSRMLS_CC );
231237
232238 intern -> visitor_data = state ;
239+
240+ /* If the cursor has a current element, we just freed it and should restore
241+ * it with a new type map applied. */
242+ if (mongoc_cursor_current (intern -> cursor )) {
243+ const bson_t * doc = mongoc_cursor_current (intern -> cursor );
244+
245+ phongo_bson_to_zval_ex (bson_get_data (doc ), doc -> len , & intern -> visitor_data );
246+ }
233247}
234248/* }}} */
235249
Original file line number Diff line number Diff line change 1+ --TEST--
2+ PHPC-849: Cursor::setTypeMap() leaks current element if called during iteration
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+ $ bulk = new MongoDB \Driver \BulkWrite ();
12+ $ bulk ->insert (['_id ' => 1 ]);
13+ $ bulk ->insert (['_id ' => 2 ]);
14+ $ bulk ->insert (['_id ' => 3 ]);
15+ $ manager ->executeBulkWrite (NS , $ bulk );
16+
17+ $ cursor = $ manager ->executeQuery (NS , new MongoDB \Driver \Query ([]));
18+ $ cursor ->setTypeMap (['root ' => 'stdClass ' ]);
19+
20+ foreach ($ cursor as $ i => $ document ) {
21+ // Type map will apply to the next iteration, since current element is already converted
22+ $ cursor ->setTypeMap (['root ' => ($ i % 2 ? 'stdClass ' : 'array ' )]);
23+ var_dump ($ document );
24+ }
25+
26+ ?>
27+ ===DONE===
28+ <?php exit (0 ); ?>
29+ --EXPECTF--
30+ object(stdClass)#%d (%d) {
31+ ["_id"]=>
32+ int(1)
33+ }
34+ array(1) {
35+ ["_id"]=>
36+ int(2)
37+ }
38+ object(stdClass)#%d (%d) {
39+ ["_id"]=>
40+ int(3)
41+ }
42+ ===DONE===
You can’t perform that action at this time.
0 commit comments