Skip to content

Commit f5d1084

Browse files
committed
Merge pull request #801
2 parents 7622c08 + cc90304 commit f5d1084

13 files changed

+220
-13
lines changed

php_phongo.c

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

240240
/* {{{ Init objects */
241-
static void phongo_cursor_init(zval *return_value, mongoc_client_t *client, mongoc_cursor_t *cursor, zval *readPreference TSRMLS_DC) /* {{{ */
241+
static void phongo_cursor_init(zval *return_value, mongoc_client_t *client, mongoc_cursor_t *cursor, zval *readPreference, zval *session TSRMLS_DC) /* {{{ */
242242
{
243243
php_phongo_cursor_t *intern;
244244

@@ -256,15 +256,24 @@ static void phongo_cursor_init(zval *return_value, mongoc_client_t *client, mong
256256
#else
257257
Z_ADDREF_P(readPreference);
258258
intern->read_preference = readPreference;
259+
#endif
260+
}
261+
262+
if (session) {
263+
#if PHP_VERSION_ID >= 70000
264+
ZVAL_ZVAL(&intern->session, session, 1, 0);
265+
#else
266+
Z_ADDREF_P(session);
267+
intern->session = session;
259268
#endif
260269
}
261270
} /* }}} */
262271

263-
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) /* {{{ */
272+
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) /* {{{ */
264273
{
265274
php_phongo_cursor_t *intern;
266275

267-
phongo_cursor_init(return_value, client, cursor, readPreference TSRMLS_CC);
276+
phongo_cursor_init(return_value, client, cursor, readPreference, session TSRMLS_CC);
268277
intern = Z_CURSOR_OBJ_P(return_value);
269278

270279
intern->database = estrdup(db);
@@ -277,11 +286,11 @@ static void phongo_cursor_init_for_command(zval *return_value, mongoc_client_t *
277286
#endif
278287
} /* }}} */
279288

280-
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) /* {{{ */
289+
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) /* {{{ */
281290
{
282291
php_phongo_cursor_t *intern;
283292

284-
phongo_cursor_init(return_value, client, cursor, readPreference TSRMLS_CC);
293+
phongo_cursor_init(return_value, client, cursor, readPreference, session TSRMLS_CC);
285294
intern = Z_CURSOR_OBJ_P(return_value);
286295

287296
/* namespace has already been validated by phongo_execute_query() */
@@ -540,11 +549,13 @@ bool phongo_parse_read_preference(zval *options, zval **zreadPreference TSRMLS_D
540549
return true;
541550
} /* }}} */
542551

543-
/* Parses the "session" option for an execute method. If mongoc_opts is not
544-
* NULL, the option will be appended. If zsession is not NULL, it will be
552+
/* Parses the "session" option for an execute method. The client object should
553+
* correspond to the Manager executing the operation and will be used to ensure
554+
* that the session is correctly associated with that client. If mongoc_opts is
555+
* not NULL, the option will be appended. If zsession is not NULL, it will be
545556
* assigned to the option. On error, false is returned and an exception is
546557
* thrown. */
547-
static bool phongo_parse_session(zval *options, bson_t *mongoc_opts, zval **zsession, mongoc_client_t *client TSRMLS_DC) /* {{{ */
558+
static bool phongo_parse_session(zval *options, mongoc_client_t *client, bson_t *mongoc_opts, zval **zsession TSRMLS_DC) /* {{{ */
548559
{
549560
zval *option = NULL;
550561
const mongoc_client_session_t *client_session;
@@ -652,7 +663,7 @@ bool phongo_execute_bulk_write(mongoc_client_t *client, const char *namespace, p
652663
return false;
653664
}
654665

655-
if (!phongo_parse_session(options, NULL, &zsession, client TSRMLS_CC)) {
666+
if (!phongo_parse_session(options, client, NULL, &zsession TSRMLS_CC)) {
656667
/* Exception should already have been thrown */
657668
return false;
658669
}
@@ -746,6 +757,7 @@ int phongo_execute_query(mongoc_client_t *client, const char *namespace, zval *z
746757
char *collname;
747758
mongoc_collection_t *collection;
748759
zval *zreadPreference = NULL;
760+
zval *zsession = NULL;
749761

750762
if (!phongo_split_namespace(namespace, &dbname, &collname)) {
751763
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s: %s", "Invalid namespace provided", namespace);
@@ -767,7 +779,7 @@ int phongo_execute_query(mongoc_client_t *client, const char *namespace, zval *z
767779
return false;
768780
}
769781

770-
if (!phongo_parse_session(options, query->opts, NULL, client TSRMLS_CC)) {
782+
if (!phongo_parse_session(options, client, query->opts, &zsession TSRMLS_CC)) {
771783
/* Exception should already have been thrown */
772784
mongoc_collection_destroy(collection);
773785
return false;
@@ -797,7 +809,8 @@ int phongo_execute_query(mongoc_client_t *client, const char *namespace, zval *z
797809
return true;
798810
}
799811

800-
phongo_cursor_init_for_query(return_value, client, cursor, namespace, zquery, zreadPreference TSRMLS_CC);
812+
phongo_cursor_init_for_query(return_value, client, cursor, namespace, zquery, zreadPreference, zsession TSRMLS_CC);
813+
801814
return true;
802815
} /* }}} */
803816

@@ -823,6 +836,7 @@ int phongo_execute_command(mongoc_client_t *client, php_phongo_command_type_t ty
823836
bson_t opts = BSON_INITIALIZER;
824837
mongoc_cursor_t *cmd_cursor;
825838
zval *zreadPreference = NULL;
839+
zval *zsession = NULL;
826840
int result;
827841

828842
command = Z_COMMAND_OBJ_P(zcommand);
@@ -839,7 +853,7 @@ int phongo_execute_command(mongoc_client_t *client, php_phongo_command_type_t ty
839853
return false;
840854
}
841855

842-
if (!phongo_parse_session(options, &opts, NULL, client TSRMLS_CC)) {
856+
if (!phongo_parse_session(options, client, &opts, &zsession TSRMLS_CC)) {
843857
/* Exception should already have been thrown */
844858
bson_destroy(&opts);
845859
return false;
@@ -920,7 +934,7 @@ int phongo_execute_command(mongoc_client_t *client, php_phongo_command_type_t ty
920934
bson_destroy(&reply);
921935
}
922936

923-
phongo_cursor_init_for_command(return_value, client, cmd_cursor, db, zcommand, zreadPreference TSRMLS_CC);
937+
phongo_cursor_init_for_command(return_value, client, cmd_cursor, db, zcommand, zreadPreference, zsession TSRMLS_CC);
924938
return true;
925939
} /* }}} */
926940
/* }}} */

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
@@ -392,6 +392,10 @@ static void php_phongo_cursor_free_object(phongo_free_object_arg *object TSRMLS_
392392
zval_ptr_dtor(&intern->read_preference);
393393
}
394394

395+
if (!Z_ISUNDEF(intern->session)) {
396+
zval_ptr_dtor(&intern->session);
397+
}
398+
395399
php_phongo_cursor_free_current(intern);
396400

397401
#if PHP_VERSION_ID < 70000
@@ -486,6 +490,18 @@ static HashTable *php_phongo_cursor_get_debug_info(zval *object, int *is_temp TS
486490
ADD_ASSOC_NULL_EX(&retval, "readPreference");
487491
}
488492

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

491507
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)