Skip to content

Commit 3af46fc

Browse files
committed
Merge branch 'v1.4'
2 parents e2aeebd + f5d1084 commit 3af46fc

13 files changed

+220
-13
lines changed

php_phongo.c

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ static void php_phongo_log(mongoc_log_level_t log_level, const char* log_domain,
209209
/* }}} */
210210

211211
/* {{{ Init objects */
212-
static void phongo_cursor_init(zval* return_value, mongoc_client_t* client, mongoc_cursor_t* cursor, zval* readPreference TSRMLS_DC) /* {{{ */
212+
static void phongo_cursor_init(zval* return_value, mongoc_client_t* client, mongoc_cursor_t* cursor, zval* readPreference, zval* session TSRMLS_DC) /* {{{ */
213213
{
214214
php_phongo_cursor_t* intern;
215215

@@ -227,15 +227,24 @@ static void phongo_cursor_init(zval* return_value, mongoc_client_t* client, mong
227227
#else
228228
Z_ADDREF_P(readPreference);
229229
intern->read_preference = readPreference;
230+
#endif
231+
}
232+
233+
if (session) {
234+
#if PHP_VERSION_ID >= 70000
235+
ZVAL_ZVAL(&intern->session, session, 1, 0);
236+
#else
237+
Z_ADDREF_P(session);
238+
intern->session = session;
230239
#endif
231240
}
232241
} /* }}} */
233242

234-
static void phongo_cursor_init_for_command(zval* return_value, mongoc_client_t* client, mongoc_cursor_t* cursor, const char* db, zval* command, zval* readPreference TSRMLS_DC) /* {{{ */
243+
static void phongo_cursor_init_for_command(zval* return_value, mongoc_client_t* client, mongoc_cursor_t* cursor, const char* db, zval* command, zval* readPreference, zval* session TSRMLS_DC) /* {{{ */
235244
{
236245
php_phongo_cursor_t* intern;
237246

238-
phongo_cursor_init(return_value, client, cursor, readPreference TSRMLS_CC);
247+
phongo_cursor_init(return_value, client, cursor, readPreference, session TSRMLS_CC);
239248
intern = Z_CURSOR_OBJ_P(return_value);
240249

241250
intern->database = estrdup(db);
@@ -248,11 +257,11 @@ static void phongo_cursor_init_for_command(zval* return_value, mongoc_client_t*
248257
#endif
249258
} /* }}} */
250259

251-
static void phongo_cursor_init_for_query(zval* return_value, mongoc_client_t* client, mongoc_cursor_t* cursor, const char* namespace, zval* query, zval* readPreference TSRMLS_DC) /* {{{ */
260+
static void phongo_cursor_init_for_query(zval* return_value, mongoc_client_t* client, mongoc_cursor_t* cursor, const char* namespace, zval* query, zval* readPreference, zval* session TSRMLS_DC) /* {{{ */
252261
{
253262
php_phongo_cursor_t* intern;
254263

255-
phongo_cursor_init(return_value, client, cursor, readPreference TSRMLS_CC);
264+
phongo_cursor_init(return_value, client, cursor, readPreference, session TSRMLS_CC);
256265
intern = Z_CURSOR_OBJ_P(return_value);
257266

258267
/* namespace has already been validated by phongo_execute_query() */
@@ -511,11 +520,13 @@ bool phongo_parse_read_preference(zval* options, zval** zreadPreference TSRMLS_D
511520
return true;
512521
} /* }}} */
513522

514-
/* Parses the "session" option for an execute method. If mongoc_opts is not
515-
* NULL, the option will be appended. If zsession is not NULL, it will be
523+
/* Parses the "session" option for an execute method. The client object should
524+
* correspond to the Manager executing the operation and will be used to ensure
525+
* that the session is correctly associated with that client. If mongoc_opts is
526+
* not NULL, the option will be appended. If zsession is not NULL, it will be
516527
* assigned to the option. On error, false is returned and an exception is
517528
* thrown. */
518-
static bool phongo_parse_session(zval* options, bson_t* mongoc_opts, zval** zsession, mongoc_client_t* client TSRMLS_DC) /* {{{ */
529+
static bool phongo_parse_session(zval *options, mongoc_client_t* client, bson_t* mongoc_opts, zval** zsession TSRMLS_DC) /* {{{ */
519530
{
520531
zval* option = NULL;
521532
const mongoc_client_session_t* client_session;
@@ -623,7 +634,7 @@ bool phongo_execute_bulk_write(mongoc_client_t* client, const char* namespace, p
623634
return false;
624635
}
625636

626-
if (!phongo_parse_session(options, NULL, &zsession, client TSRMLS_CC)) {
637+
if (!phongo_parse_session(options, client, NULL, &zsession TSRMLS_CC)) {
627638
/* Exception should already have been thrown */
628639
return false;
629640
}
@@ -716,6 +727,7 @@ int phongo_execute_query(mongoc_client_t* client, const char* namespace, zval* z
716727
char* collname;
717728
mongoc_collection_t* collection;
718729
zval* zreadPreference = NULL;
730+
zval* zsession = NULL;
719731

720732
if (!phongo_split_namespace(namespace, &dbname, &collname)) {
721733
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s: %s", "Invalid namespace provided", namespace);
@@ -737,7 +749,7 @@ int phongo_execute_query(mongoc_client_t* client, const char* namespace, zval* z
737749
return false;
738750
}
739751

740-
if (!phongo_parse_session(options, query->opts, NULL, client TSRMLS_CC)) {
752+
if (!phongo_parse_session(options, client, query->opts, &zsession TSRMLS_CC)) {
741753
/* Exception should already have been thrown */
742754
mongoc_collection_destroy(collection);
743755
return false;
@@ -767,7 +779,8 @@ int phongo_execute_query(mongoc_client_t* client, const char* namespace, zval* z
767779
return true;
768780
}
769781

770-
phongo_cursor_init_for_query(return_value, client, cursor, namespace, zquery, zreadPreference TSRMLS_CC);
782+
phongo_cursor_init_for_query(return_value, client, cursor, namespace, zquery, zreadPreference, zsession TSRMLS_CC);
783+
771784
return true;
772785
} /* }}} */
773786

@@ -793,6 +806,7 @@ int phongo_execute_command(mongoc_client_t* client, php_phongo_command_type_t ty
793806
bson_t opts = BSON_INITIALIZER;
794807
mongoc_cursor_t* cmd_cursor;
795808
zval* zreadPreference = NULL;
809+
zval* zsession = NULL;
796810
int result;
797811

798812
command = Z_COMMAND_OBJ_P(zcommand);
@@ -809,7 +823,7 @@ int phongo_execute_command(mongoc_client_t* client, php_phongo_command_type_t ty
809823
return false;
810824
}
811825

812-
if (!phongo_parse_session(options, &opts, NULL, client TSRMLS_CC)) {
826+
if (!phongo_parse_session(options, client, &opts, &zsession TSRMLS_CC)) {
813827
/* Exception should already have been thrown */
814828
bson_destroy(&opts);
815829
return false;
@@ -908,7 +922,7 @@ int phongo_execute_command(mongoc_client_t* client, php_phongo_command_type_t ty
908922
bson_destroy(&reply);
909923
}
910924

911-
phongo_cursor_init_for_command(return_value, client, cmd_cursor, db, zcommand, zreadPreference TSRMLS_CC);
925+
phongo_cursor_init_for_command(return_value, client, cmd_cursor, db, zcommand, zreadPreference, zsession TSRMLS_CC);
912926
return true;
913927
} /* }}} */
914928
/* }}} */

php_phongo_structs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ typedef struct {
6565
PHONGO_STRUCT_ZVAL query;
6666
PHONGO_STRUCT_ZVAL command;
6767
PHONGO_STRUCT_ZVAL read_preference;
68+
PHONGO_STRUCT_ZVAL session;
6869
PHONGO_ZEND_OBJECT_POST
6970
} php_phongo_cursor_t;
7071

src/MongoDB/Cursor.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,10 @@ static void php_phongo_cursor_free_object(phongo_free_object_arg* object TSRMLS_
394394
zval_ptr_dtor(&intern->read_preference);
395395
}
396396

397+
if (!Z_ISUNDEF(intern->session)) {
398+
zval_ptr_dtor(&intern->session);
399+
}
400+
397401
php_phongo_cursor_free_current(intern);
398402

399403
#if PHP_VERSION_ID < 70000
@@ -483,6 +487,18 @@ static HashTable* php_phongo_cursor_get_debug_info(zval* object, int* is_temp TS
483487
ADD_ASSOC_NULL_EX(&retval, "readPreference");
484488
}
485489

490+
if (!Z_ISUNDEF(intern->session)) {
491+
#if PHP_VERSION_ID >= 70000
492+
ADD_ASSOC_ZVAL_EX(&retval, "session", &intern->session);
493+
Z_ADDREF(intern->session);
494+
#else
495+
ADD_ASSOC_ZVAL_EX(&retval, "session", intern->session);
496+
Z_ADDREF_P(intern->session);
497+
#endif
498+
} else {
499+
ADD_ASSOC_NULL_EX(&retval, "session");
500+
}
501+
486502
ADD_ASSOC_BOOL_EX(&retval, "isDead", !mongoc_cursor_is_alive(intern->cursor));
487503

488504
ADD_ASSOC_LONG_EX(&retval, "currentIndex", intern->current);

tests/cursor/bug1151-001.phpt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
PHPC-1151: Segfault if session unset before first getMore (find)
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php NEEDS_CRYPTO(); ?>
6+
<?php NEEDS('STANDALONE'); ?>
7+
<?php NEEDS_ATLEAST_MONGODB_VERSION(STANDALONE, "3.6"); ?>
8+
<?php CLEANUP(STANDALONE); ?>
9+
--FILE--
10+
<?php
11+
require_once __DIR__ . "/../utils/basic.inc";
12+
13+
$manager = new MongoDB\Driver\Manager(STANDALONE);
14+
15+
$bulk = new MongoDB\Driver\BulkWrite;
16+
$bulk->insert(['_id' => 1]);
17+
$bulk->insert(['_id' => 2]);
18+
$bulk->insert(['_id' => 3]);
19+
$manager->executeBulkWrite(NS, $bulk);
20+
21+
$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
22+
$session = $manager->startSession();
23+
24+
$cursor = $manager->executeQuery(NS, $query, ['session' => $session]);
25+
26+
foreach ($cursor as $document) {
27+
unset($session);
28+
echo $document->_id, "\n";
29+
}
30+
31+
?>
32+
===DONE===
33+
<?php exit(0); ?>
34+
--EXPECT--
35+
1
36+
2
37+
3
38+
===DONE===

tests/cursor/bug1151-002.phpt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
--TEST--
2+
PHPC-1151: Segfault if session unset before first getMore (aggregate)
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php NEEDS_CRYPTO(); ?>
6+
<?php NEEDS('STANDALONE'); ?>
7+
<?php NEEDS_ATLEAST_MONGODB_VERSION(STANDALONE, "3.6"); ?>
8+
<?php CLEANUP(STANDALONE); ?>
9+
--FILE--
10+
<?php
11+
require_once __DIR__ . "/../utils/basic.inc";
12+
13+
$manager = new MongoDB\Driver\Manager(STANDALONE);
14+
15+
$bulk = new MongoDB\Driver\BulkWrite;
16+
$bulk->insert(['_id' => 1]);
17+
$bulk->insert(['_id' => 2]);
18+
$bulk->insert(['_id' => 3]);
19+
$manager->executeBulkWrite(NS, $bulk);
20+
21+
$command = new MongoDB\Driver\Command([
22+
'aggregate' => COLLECTION_NAME,
23+
'pipeline' => [],
24+
'cursor' => ['batchSize' => 2],
25+
]);
26+
$session = $manager->startSession();
27+
28+
$cursor = $manager->executeReadCommand(DATABASE_NAME, $command, ['session' => $session]);
29+
30+
foreach ($cursor as $document) {
31+
unset($session);
32+
echo $document->_id, "\n";
33+
}
34+
35+
?>
36+
===DONE===
37+
<?php exit(0); ?>
38+
--EXPECT--
39+
1
40+
2
41+
3
42+
===DONE===

tests/cursor/bug1151-003.phpt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
PHPC-1151: Segfault if session unset before cursor is killed (find)
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php NEEDS_CRYPTO(); ?>
6+
<?php NEEDS('STANDALONE'); ?>
7+
<?php NEEDS_ATLEAST_MONGODB_VERSION(STANDALONE, "3.6"); ?>
8+
<?php CLEANUP(STANDALONE); ?>
9+
--FILE--
10+
<?php
11+
require_once __DIR__ . "/../utils/basic.inc";
12+
13+
$manager = new MongoDB\Driver\Manager(STANDALONE);
14+
15+
$bulk = new MongoDB\Driver\BulkWrite;
16+
$bulk->insert(['_id' => 1]);
17+
$bulk->insert(['_id' => 2]);
18+
$bulk->insert(['_id' => 3]);
19+
$manager->executeBulkWrite(NS, $bulk);
20+
21+
$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
22+
$session = $manager->startSession();
23+
24+
$cursor = $manager->executeQuery(NS, $query, ['session' => $session]);
25+
unset($session);
26+
unset($cursor);
27+
28+
?>
29+
===DONE===
30+
<?php exit(0); ?>
31+
--EXPECT--
32+
===DONE===

tests/cursor/bug1151-004.phpt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
PHPC-1151: Segfault if session unset before cursor is killed (aggregate)
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php NEEDS_CRYPTO(); ?>
6+
<?php NEEDS('STANDALONE'); ?>
7+
<?php NEEDS_ATLEAST_MONGODB_VERSION(STANDALONE, "3.6"); ?>
8+
<?php CLEANUP(STANDALONE); ?>
9+
--FILE--
10+
<?php
11+
require_once __DIR__ . "/../utils/basic.inc";
12+
13+
$manager = new MongoDB\Driver\Manager(STANDALONE);
14+
15+
$bulk = new MongoDB\Driver\BulkWrite;
16+
$bulk->insert(['_id' => 1]);
17+
$bulk->insert(['_id' => 2]);
18+
$bulk->insert(['_id' => 3]);
19+
$manager->executeBulkWrite(NS, $bulk);
20+
21+
$command = new MongoDB\Driver\Command([
22+
'aggregate' => COLLECTION_NAME,
23+
'pipeline' => [],
24+
'cursor' => ['batchSize' => 2],
25+
]);
26+
$session = $manager->startSession();
27+
28+
$cursor = $manager->executeReadCommand(DATABASE_NAME, $command, ['session' => $session]);
29+
unset($session);
30+
unset($cursor);
31+
32+
?>
33+
===DONE===
34+
<?php exit(0); ?>
35+
--EXPECT--
36+
===DONE===

tests/manager/manager-executeCommand-001.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ object(MongoDB\Driver\Cursor)#%d (%d) {
5454
}
5555
["readPreference"]=>
5656
NULL
57+
["session"]=>
58+
NULL
5759
["isDead"]=>
5860
bool(false)
5961
["currentIndex"]=>

tests/manager/manager-executeQuery-001.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ object(MongoDB\Driver\Cursor)#%d (%d) {
6464
NULL
6565
["readPreference"]=>
6666
NULL
67+
["session"]=>
68+
NULL
6769
["isDead"]=>
6870
bool(false)
6971
["currentIndex"]=>

tests/manager/manager-executeQuery-002.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ object(MongoDB\Driver\Cursor)#%d (%d) {
6464
NULL
6565
["readPreference"]=>
6666
NULL
67+
["session"]=>
68+
NULL
6769
["isDead"]=>
6870
bool(false)
6971
["currentIndex"]=>

tests/readPreference/bug0146-001.phpt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ object(MongoDB\Driver\Cursor)#%d (%d) {
5858
["mode"]=>
5959
string(7) "primary"
6060
}
61+
["session"]=>
62+
NULL
6163
["isDead"]=>
6264
bool(true)
6365
["currentIndex"]=>
@@ -96,6 +98,8 @@ object(MongoDB\Driver\Cursor)#%d (%d) {
9698
["mode"]=>
9799
string(16) "primaryPreferred"
98100
}
101+
["session"]=>
102+
NULL
99103
["isDead"]=>
100104
bool(true)
101105
["currentIndex"]=>
@@ -134,6 +138,8 @@ object(MongoDB\Driver\Cursor)#%d (%d) {
134138
["mode"]=>
135139
string(9) "secondary"
136140
}
141+
["session"]=>
142+
NULL
137143
["isDead"]=>
138144
bool(true)
139145
["currentIndex"]=>
@@ -172,6 +178,8 @@ object(MongoDB\Driver\Cursor)#%d (%d) {
172178
["mode"]=>
173179
string(18) "secondaryPreferred"
174180
}
181+
["session"]=>
182+
NULL
175183
["isDead"]=>
176184
bool(true)
177185
["currentIndex"]=>
@@ -210,6 +218,8 @@ object(MongoDB\Driver\Cursor)#%d (%d) {
210218
["mode"]=>
211219
string(7) "nearest"
212220
}
221+
["session"]=>
222+
NULL
213223
["isDead"]=>
214224
bool(true)
215225
["currentIndex"]=>

0 commit comments

Comments
 (0)