From 05fcc2ea4f2e593cdfbcd606e4cef7fc87d953c8 Mon Sep 17 00:00:00 2001 From: Jeremy Mikola Date: Sat, 28 May 2016 19:42:11 -0400 Subject: [PATCH] PHPC-671: Avoid mongoc_client_t use-after-free by Cursor and Server --- php_phongo.c | 53 +++++++++++++++++++++++------- php_phongo.h | 8 ++--- php_phongo_structs-5.h | 3 ++ php_phongo_structs-7.h | 3 ++ src/MongoDB/Cursor.c | 9 +++-- src/MongoDB/Manager.c | 24 ++++---------- src/MongoDB/Server.c | 21 +++++++++--- src/MongoDB/WriteResult.c | 9 +++-- tests/cursor/bug0671-001.phpt | 26 +++++++++++++++ tests/server/bug0671-002.phpt | 25 ++++++++++++++ tests/writeResult/bug0671-003.phpt | 32 ++++++++++++++++++ 11 files changed, 171 insertions(+), 42 deletions(-) create mode 100644 tests/cursor/bug0671-001.phpt create mode 100644 tests/server/bug0671-002.phpt create mode 100644 tests/writeResult/bug0671-003.phpt diff --git a/php_phongo.c b/php_phongo.c index b1a81e07..cbc033f5 100644 --- a/php_phongo.c +++ b/php_phongo.c @@ -224,7 +224,7 @@ static void php_phongo_log(mongoc_log_level_t log_level, const char *log_domain, /* }}} */ /* {{{ Init objects */ -static void phongo_cursor_init(zval *return_value, mongoc_cursor_t *cursor, mongoc_client_t *client TSRMLS_DC) /* {{{ */ +static void phongo_cursor_init(zval *return_value, zval *manager, mongoc_cursor_t *cursor TSRMLS_DC) /* {{{ */ { php_phongo_cursor_t *intern; @@ -233,18 +233,32 @@ static void phongo_cursor_init(zval *return_value, mongoc_cursor_t *cursor, mong intern = Z_CURSOR_OBJ_P(return_value); intern->cursor = cursor; intern->server_id = mongoc_cursor_get_hint(cursor); - intern->client = client; + intern->client = Z_MANAGER_OBJ_P(manager)->client; + +#if PHP_VERSION_ID >= 70000 + ZVAL_COPY(&intern->manager, manager); +#else + Z_ADDREF_P(manager); + intern->manager = manager; +#endif } /* }}} */ -void phongo_server_init(zval *return_value, mongoc_client_t *client, int server_id TSRMLS_DC) /* {{{ */ +void phongo_server_init(zval *return_value, zval *manager, int server_id TSRMLS_DC) /* {{{ */ { php_phongo_server_t *server; object_init_ex(return_value, php_phongo_server_ce); server = Z_SERVER_OBJ_P(return_value); - server->client = client; server->server_id = server_id; + server->client = Z_MANAGER_OBJ_P(manager)->client; + +#if PHP_VERSION_ID >= 70000 + ZVAL_COPY(&server->manager, manager); +#else + Z_ADDREF_P(manager); + server->manager = manager; +#endif } /* }}} */ @@ -467,7 +481,7 @@ zend_bool phongo_writeerror_init(zval *return_value, bson_t *bson TSRMLS_DC) /* return true; } /* }}} */ -php_phongo_writeresult_t *phongo_writeresult_init(zval *return_value, bson_t *reply, mongoc_client_t *client, int server_id TSRMLS_DC) /* {{{ */ +php_phongo_writeresult_t *phongo_writeresult_init(zval *return_value, bson_t *reply, zval *manager, int server_id TSRMLS_DC) /* {{{ */ { php_phongo_writeresult_t *writeresult; @@ -475,8 +489,15 @@ php_phongo_writeresult_t *phongo_writeresult_init(zval *return_value, bson_t *re writeresult = Z_WRITERESULT_OBJ_P(return_value); writeresult->reply = bson_copy(reply); - writeresult->client = client; writeresult->server_id = server_id; + writeresult->client = Z_MANAGER_OBJ_P(manager)->client; + +#if PHP_VERSION_ID >= 70000 + ZVAL_COPY(&writeresult->manager, manager); +#else + Z_ADDREF_P(manager); + writeresult->manager = manager; +#endif return writeresult; } /* }}} */ @@ -506,8 +527,9 @@ mongoc_bulk_operation_t *phongo_bulkwrite_init(zend_bool ordered) { /* {{{ */ return mongoc_bulk_operation_new(ordered); } /* }}} */ -bool phongo_execute_write(mongoc_client_t *client, const char *namespace, mongoc_bulk_operation_t *bulk, const mongoc_write_concern_t *write_concern, int server_id, zval *return_value, int return_value_used TSRMLS_DC) /* {{{ */ +bool phongo_execute_write(zval *manager, const char *namespace, mongoc_bulk_operation_t *bulk, const mongoc_write_concern_t *write_concern, int server_id, zval *return_value, int return_value_used TSRMLS_DC) /* {{{ */ { + mongoc_client_t *client; bson_error_t error; char *dbname; char *collname; @@ -515,6 +537,8 @@ bool phongo_execute_write(mongoc_client_t *client, const char *namespace, mongoc bson_t reply = BSON_INITIALIZER; php_phongo_writeresult_t *writeresult; + client = Z_MANAGER_OBJ_P(manager)->client; + if (!phongo_split_namespace(namespace, &dbname, &collname)) { phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s: %s", "Invalid namespace provided", namespace); return false; @@ -553,7 +577,7 @@ bool phongo_execute_write(mongoc_client_t *client, const char *namespace, mongoc return false; } - writeresult = phongo_writeresult_init(return_value, &reply, client, bulk->hint TSRMLS_CC); + writeresult = phongo_writeresult_init(return_value, &reply, manager, bulk->hint TSRMLS_CC); writeresult->write_concern = mongoc_write_concern_copy(write_concern); /* The Write failed */ @@ -571,14 +595,17 @@ bool phongo_execute_write(mongoc_client_t *client, const char *namespace, mongoc return success; } /* }}} */ -int phongo_execute_query(mongoc_client_t *client, const char *namespace, const php_phongo_query_t *query, const mongoc_read_prefs_t *read_preference, int server_id, zval *return_value, int return_value_used TSRMLS_DC) /* {{{ */ +int phongo_execute_query(zval *manager, const char *namespace, const php_phongo_query_t *query, const mongoc_read_prefs_t *read_preference, int server_id, zval *return_value, int return_value_used TSRMLS_DC) /* {{{ */ { + mongoc_client_t *client; const bson_t *doc = NULL; mongoc_cursor_t *cursor; char *dbname; char *collname; mongoc_collection_t *collection; + client = Z_MANAGER_OBJ_P(manager)->client; + if (!phongo_split_namespace(namespace, &dbname, &collname)) { phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s: %s", "Invalid namespace provided", namespace); return false; @@ -626,17 +653,19 @@ int phongo_execute_query(mongoc_client_t *client, const char *namespace, const p return true; } - phongo_cursor_init(return_value, cursor, client TSRMLS_CC); + phongo_cursor_init(return_value, manager, cursor TSRMLS_CC); return true; } /* }}} */ -int phongo_execute_command(mongoc_client_t *client, const char *db, const bson_t *command, const mongoc_read_prefs_t *read_preference, int server_id, zval *return_value, int return_value_used TSRMLS_DC) /* {{{ */ +int phongo_execute_command(zval *manager, const char *db, const bson_t *command, const mongoc_read_prefs_t *read_preference, int server_id, zval *return_value, int return_value_used TSRMLS_DC) /* {{{ */ { + mongoc_client_t *client; mongoc_cursor_t *cursor; const bson_t *doc; bson_iter_t iter; bson_iter_t child; + client = Z_MANAGER_OBJ_P(manager)->client; cursor = mongoc_client_command(client, db, MONGOC_QUERY_NONE, 0, 1, 0, command, NULL, read_preference); if (server_id > 0) { @@ -702,7 +731,7 @@ int phongo_execute_command(mongoc_client_t *client, const char *db, const bson_t mongoc_cursor_next(cursor, &doc); } - phongo_cursor_init(return_value, cursor, client TSRMLS_CC); + phongo_cursor_init(return_value, manager, cursor TSRMLS_CC); return true; } /* }}} */ diff --git a/php_phongo.h b/php_phongo.h index f56cb7a2..59c53a10 100644 --- a/php_phongo.h +++ b/php_phongo.h @@ -114,15 +114,15 @@ void phongo_throw_exception_from_bson_error_t(bson_error_t *error TSRMLS_DC); PHONGO_API zend_object_handlers *phongo_get_std_object_handlers(void); -void phongo_server_init (zval *return_value, mongoc_client_t *client, int server_id TSRMLS_DC); +void phongo_server_init (zval *return_value, zval *manager, int server_id TSRMLS_DC); void phongo_readconcern_init (zval *return_value, const mongoc_read_concern_t *read_concern TSRMLS_DC); void phongo_readpreference_init (zval *return_value, const mongoc_read_prefs_t *read_prefs TSRMLS_DC); void phongo_writeconcern_init (zval *return_value, const mongoc_write_concern_t *write_concern TSRMLS_DC); bool phongo_query_init (php_phongo_query_t *query, bson_t *filter, bson_t *options TSRMLS_DC); mongoc_bulk_operation_t* phongo_bulkwrite_init (zend_bool ordered); -bool phongo_execute_write (mongoc_client_t *client, const char *namespace, mongoc_bulk_operation_t *bulk, const mongoc_write_concern_t *write_concern, int server_id, zval *return_value, int return_value_used TSRMLS_DC); -int phongo_execute_command (mongoc_client_t *client, const char *db, const bson_t *command, const mongoc_read_prefs_t *read_preference, int server_id, zval *return_value, int return_value_used TSRMLS_DC); -int phongo_execute_query (mongoc_client_t *client, const char *namespace, const php_phongo_query_t *query, const mongoc_read_prefs_t *read_preference, int server_id, zval *return_value, int return_value_used TSRMLS_DC); +bool phongo_execute_write (zval *manager, const char *namespace, mongoc_bulk_operation_t *bulk, const mongoc_write_concern_t *write_concern, int server_id, zval *return_value, int return_value_used TSRMLS_DC); +int phongo_execute_command (zval *manager, const char *db, const bson_t *command, const mongoc_read_prefs_t *read_preference, int server_id, zval *return_value, int return_value_used TSRMLS_DC); +int phongo_execute_query (zval *manager, const char *namespace, const php_phongo_query_t *query, const mongoc_read_prefs_t *read_preference, int server_id, zval *return_value, int return_value_used TSRMLS_DC); mongoc_stream_t* phongo_stream_initiator (const mongoc_uri_t *uri, const mongoc_host_list_t *host, void *user_data, bson_error_t *error); const mongoc_read_concern_t* phongo_read_concern_from_zval (zval *zread_concern TSRMLS_DC); diff --git a/php_phongo_structs-5.h b/php_phongo_structs-5.h index e50cb80e..d24f235c 100644 --- a/php_phongo_structs-5.h +++ b/php_phongo_structs-5.h @@ -40,6 +40,7 @@ typedef struct { typedef struct { zend_object std; mongoc_cursor_t *cursor; + zval *manager; mongoc_client_t *client; int server_id; php_phongo_bson_state visitor_data; @@ -80,6 +81,7 @@ typedef struct { typedef struct { zend_object std; + zval *manager; mongoc_client_t *client; int server_id; } php_phongo_server_t; @@ -113,6 +115,7 @@ typedef struct { zend_object std; mongoc_write_concern_t *write_concern; bson_t *reply; + zval *manager; mongoc_client_t *client; int server_id; } php_phongo_writeresult_t; diff --git a/php_phongo_structs-7.h b/php_phongo_structs-7.h index b879880f..d596d3ab 100644 --- a/php_phongo_structs-7.h +++ b/php_phongo_structs-7.h @@ -39,6 +39,7 @@ typedef struct { typedef struct { mongoc_cursor_t *cursor; + zval manager; mongoc_client_t *client; int server_id; php_phongo_bson_state visitor_data; @@ -79,6 +80,7 @@ typedef struct { } php_phongo_readpreference_t; typedef struct { + zval manager; mongoc_client_t *client; int server_id; zend_object std; @@ -112,6 +114,7 @@ typedef struct { typedef struct { mongoc_write_concern_t *write_concern; bson_t *reply; + zval manager; mongoc_client_t *client; int server_id; zend_object std; diff --git a/src/MongoDB/Cursor.c b/src/MongoDB/Cursor.c index a6448a34..0a461cec 100644 --- a/src/MongoDB/Cursor.c +++ b/src/MongoDB/Cursor.c @@ -157,8 +157,11 @@ PHP_METHOD(Cursor, getServer) return; } - - phongo_server_init(return_value, intern->cursor->client, intern->server_id TSRMLS_CC); +#if PHP_VERSION_ID >= 70000 + phongo_server_init(return_value, &intern->manager, intern->server_id TSRMLS_CC); +#else + phongo_server_init(return_value, intern->manager, intern->server_id TSRMLS_CC); +#endif } /* }}} */ @@ -222,6 +225,8 @@ static void php_phongo_cursor_free_object(phongo_free_object_arg *object TSRMLS_ php_phongo_cursor_free(intern); + zval_ptr_dtor(&intern->manager); + #if PHP_VERSION_ID < 70000 efree(intern); #endif diff --git a/src/MongoDB/Manager.c b/src/MongoDB/Manager.c index 536159b1..4c26be7b 100644 --- a/src/MongoDB/Manager.c +++ b/src/MongoDB/Manager.c @@ -89,7 +89,6 @@ PHP_METHOD(Manager, __construct) Execute a command */ PHP_METHOD(Manager, executeCommand) { - php_phongo_manager_t *intern; char *db; phongo_zpp_char_len db_len; zval *command; @@ -98,23 +97,19 @@ PHP_METHOD(Manager, executeCommand) DECLARE_RETURN_VALUE_USED SUPPRESS_UNUSED_WARNING(return_value_ptr) - - intern = Z_MANAGER_OBJ_P(getThis()); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO|O!", &db, &db_len, &command, php_phongo_command_ce, &readPreference, php_phongo_readpreference_ce) == FAILURE) { return; } cmd = Z_COMMAND_OBJ_P(command); - phongo_execute_command(intern->client, db, cmd->bson, phongo_read_preference_from_zval(readPreference TSRMLS_CC), -1, return_value, return_value_used TSRMLS_CC); + phongo_execute_command(getThis(), db, cmd->bson, phongo_read_preference_from_zval(readPreference TSRMLS_CC), -1, return_value, return_value_used TSRMLS_CC); } /* }}} */ /* {{{ proto MongoDB\Driver\Cursor Manager::executeQuery(string $namespace, MongoDB\Driver\Query $zquery[, MongoDB\Driver\ReadPreference $readPreference = null]) Execute a Query */ PHP_METHOD(Manager, executeQuery) { - php_phongo_manager_t *intern; char *namespace; phongo_zpp_char_len namespace_len; zval *zquery; @@ -122,22 +117,18 @@ PHP_METHOD(Manager, executeQuery) DECLARE_RETURN_VALUE_USED SUPPRESS_UNUSED_WARNING(return_value_ptr) - - intern = Z_MANAGER_OBJ_P(getThis()); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO|O!", &namespace, &namespace_len, &zquery, php_phongo_query_ce, &readPreference, php_phongo_readpreference_ce) == FAILURE) { return; } - phongo_execute_query(intern->client, namespace, phongo_query_from_zval(zquery TSRMLS_CC), phongo_read_preference_from_zval(readPreference TSRMLS_CC), -1, return_value, return_value_used TSRMLS_CC); + phongo_execute_query(getThis(), namespace, phongo_query_from_zval(zquery TSRMLS_CC), phongo_read_preference_from_zval(readPreference TSRMLS_CC), -1, return_value, return_value_used TSRMLS_CC); } /* }}} */ /* {{{ proto MongoDB\Driver\WriteResult Manager::executeBulkWrite(string $namespace, MongoDB\Driver\BulkWrite $zbulk[, MongoDB\Driver\WriteConcern $writeConcern = null]) Executes a write operation bulk (e.g. insert, update, delete) */ PHP_METHOD(Manager, executeBulkWrite) { - php_phongo_manager_t *intern; char *namespace; phongo_zpp_char_len namespace_len; zval *zbulk; @@ -146,16 +137,13 @@ PHP_METHOD(Manager, executeBulkWrite) DECLARE_RETURN_VALUE_USED SUPPRESS_UNUSED_WARNING(return_value_ptr) - - intern = Z_MANAGER_OBJ_P(getThis()); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO|O!", &namespace, &namespace_len, &zbulk, php_phongo_bulkwrite_ce, &zwrite_concern, php_phongo_writeconcern_ce) == FAILURE) { return; } bulk = Z_BULKWRITE_OBJ_P(zbulk); - phongo_execute_write(intern->client, namespace, bulk->bulk, phongo_write_concern_from_zval(zwrite_concern TSRMLS_CC), -1, return_value, return_value_used TSRMLS_CC); + phongo_execute_write(getThis(), namespace, bulk->bulk, phongo_write_concern_from_zval(zwrite_concern TSRMLS_CC), -1, return_value, return_value_used TSRMLS_CC); } /* }}} */ @@ -230,12 +218,12 @@ PHP_METHOD(Manager, getServers) } #if PHP_VERSION_ID >= 70000 - phongo_server_init(&obj, intern->client, ((mongoc_server_description_t *)set->items[i].item)->id TSRMLS_CC); + phongo_server_init(&obj, getThis(), ((mongoc_server_description_t *)set->items[i].item)->id TSRMLS_CC); add_next_index_zval(return_value, &obj); #else MAKE_STD_ZVAL(obj); - phongo_server_init(obj, intern->client, sd->id TSRMLS_CC); + phongo_server_init(obj, getThis(), sd->id TSRMLS_CC); add_next_index_zval(return_value, obj); #endif } @@ -281,7 +269,7 @@ PHP_METHOD(Manager, selectServer) readPreference = phongo_read_preference_from_zval(zreadPreference TSRMLS_CC); selected_server = mongoc_topology_select(intern->client->topology, MONGOC_SS_READ, readPreference, MONGOC_SS_DEFAULT_LOCAL_THRESHOLD_MS, &error); if (selected_server) { - phongo_server_init(return_value, intern->client, selected_server->id TSRMLS_CC); + phongo_server_init(return_value, getThis(), selected_server->id TSRMLS_CC); mongoc_server_description_destroy(selected_server); } else { /* Check for connection related exceptions */ diff --git a/src/MongoDB/Server.c b/src/MongoDB/Server.c index 65e03131..e0092779 100644 --- a/src/MongoDB/Server.c +++ b/src/MongoDB/Server.c @@ -80,7 +80,11 @@ PHP_METHOD(Server, executeCommand) cmd = Z_COMMAND_OBJ_P(command); - phongo_execute_command(intern->client, db, cmd->bson, phongo_read_preference_from_zval(readPreference TSRMLS_CC), intern->server_id, return_value, return_value_used TSRMLS_CC); +#if PHP_VERSION_ID >= 70000 + phongo_execute_command(&intern->manager, db, cmd->bson, phongo_read_preference_from_zval(readPreference TSRMLS_CC), intern->server_id, return_value, return_value_used TSRMLS_CC); +#else + phongo_execute_command(intern->manager, db, cmd->bson, phongo_read_preference_from_zval(readPreference TSRMLS_CC), intern->server_id, return_value, return_value_used TSRMLS_CC); +#endif } /* }}} */ /* {{{ proto MongoDB\Driver\Cursor Server::executeQuery(string $namespace, MongoDB\Driver\Query $zquery[, MongoDB\Driver\ReadPreference $readPreference = null])) @@ -102,8 +106,11 @@ PHP_METHOD(Server, executeQuery) return; } - - phongo_execute_query(intern->client, namespace, phongo_query_from_zval(zquery TSRMLS_CC), phongo_read_preference_from_zval(readPreference TSRMLS_CC), intern->server_id, return_value, return_value_used TSRMLS_CC); +#if PHP_VERSION_ID >= 70000 + phongo_execute_query(&intern->manager, namespace, phongo_query_from_zval(zquery TSRMLS_CC), phongo_read_preference_from_zval(readPreference TSRMLS_CC), intern->server_id, return_value, return_value_used TSRMLS_CC); +#else + phongo_execute_query(intern->manager, namespace, phongo_query_from_zval(zquery TSRMLS_CC), phongo_read_preference_from_zval(readPreference TSRMLS_CC), intern->server_id, return_value, return_value_used TSRMLS_CC); +#endif } /* }}} */ /* {{{ proto MongoDB\Driver\WriteResult Server::executeBulkWrite(string $namespace, MongoDB\Driver\BulkWrite $zbulk[, MongoDB\Driver\WriteConcern $writeConcern = null]) @@ -128,7 +135,11 @@ PHP_METHOD(Server, executeBulkWrite) bulk = Z_BULKWRITE_OBJ_P(zbulk); - phongo_execute_write(intern->client, namespace, bulk->bulk, phongo_write_concern_from_zval(zwrite_concern TSRMLS_CC), intern->server_id, return_value, return_value_used TSRMLS_CC); +#if PHP_VERSION_ID >= 70000 + phongo_execute_write(&intern->manager, namespace, bulk->bulk, phongo_write_concern_from_zval(zwrite_concern TSRMLS_CC), intern->server_id, return_value, return_value_used TSRMLS_CC); +#else + phongo_execute_write(intern->manager, namespace, bulk->bulk, phongo_write_concern_from_zval(zwrite_concern TSRMLS_CC), intern->server_id, return_value, return_value_used TSRMLS_CC); +#endif } /* }}} */ /* {{{ proto string Server::getHost() @@ -522,6 +533,8 @@ static void php_phongo_server_free_object(phongo_free_object_arg *object TSRMLS_ zend_object_std_dtor(&intern->std TSRMLS_CC); + zval_ptr_dtor(&intern->manager); + #if PHP_VERSION_ID < 70000 efree(intern); #endif diff --git a/src/MongoDB/WriteResult.c b/src/MongoDB/WriteResult.c index ddc5b609..310346c7 100644 --- a/src/MongoDB/WriteResult.c +++ b/src/MongoDB/WriteResult.c @@ -155,8 +155,11 @@ PHP_METHOD(WriteResult, getServer) return; } - - phongo_server_init(return_value, intern->client, intern->server_id TSRMLS_CC); +#if PHP_VERSION_ID >= 70000 + phongo_server_init(return_value, &intern->manager, intern->server_id TSRMLS_CC); +#else + phongo_server_init(return_value, intern->manager, intern->server_id TSRMLS_CC); +#endif } /* }}} */ /* {{{ proto array WriteResult::getUpsertedIds() @@ -422,6 +425,8 @@ static void php_phongo_writeresult_free_object(phongo_free_object_arg *object TS mongoc_write_concern_destroy(intern->write_concern); } + zval_ptr_dtor(&intern->manager); + #if PHP_VERSION_ID < 70000 efree(intern); #endif diff --git a/tests/cursor/bug0671-001.phpt b/tests/cursor/bug0671-001.phpt new file mode 100644 index 00000000..61dac40c --- /dev/null +++ b/tests/cursor/bug0671-001.phpt @@ -0,0 +1,26 @@ +--TEST-- +PHPC-671: Segfault if Manager is already freed when destructing live Cursor +--SKIPIF-- + +--FILE-- +insert(['_id' => 1]); +$bulk->insert(['_id' => 2]); +$bulk->insert(['_id' => 3]); +$manager->executeBulkWrite(NS, $bulk); + +$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([], ['batchSize' => 2])); + +unset($manager); +unset($cursor); + +?> +===DONE=== + +--EXPECT-- +===DONE=== diff --git a/tests/server/bug0671-002.phpt b/tests/server/bug0671-002.phpt new file mode 100644 index 00000000..b621ca49 --- /dev/null +++ b/tests/server/bug0671-002.phpt @@ -0,0 +1,25 @@ +--TEST-- +PHPC-671: Segfault if Manager is already freed when using selected Server +--SKIPIF-- + +--FILE-- +selectServer(new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_PRIMARY)); + +unset($manager); + +$cursor = $server->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1])); +var_dump($cursor->toArray()[0]); + +?> +===DONE=== + +--EXPECTF-- +object(stdClass)#%d (%d) { + ["ok"]=> + float(1) +} +===DONE=== diff --git a/tests/writeResult/bug0671-003.phpt b/tests/writeResult/bug0671-003.phpt new file mode 100644 index 00000000..e684ee94 --- /dev/null +++ b/tests/writeResult/bug0671-003.phpt @@ -0,0 +1,32 @@ +--TEST-- +PHPC-671: Segfault if Manager is already freed when using WriteResult's Server +--SKIPIF-- + +--FILE-- +insert(['_id' => 1]); +$writeResult = $manager->executeBulkWrite(NS, $bulk); + +unset($manager); + +$server = $writeResult->getServer(); + +/* WriteResult only uses the client to construct a Server. We need to interact + * with the Server to test for a user-after-free. */ +$cursor = $server->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1])); +var_dump($cursor->toArray()[0]); + +?> +===DONE=== + +--EXPECTF-- +object(stdClass)#%d (%d) { + ["ok"]=> + float(1) +} +===DONE===