From ad1f3f049f5c101a8b4f89f13e6384bbefb6ef6c Mon Sep 17 00:00:00 2001 From: Jeremy Mikola Date: Wed, 5 Jul 2017 17:15:20 -0400 Subject: [PATCH] PHPC-939: Don't modify std props in BSON get_properties handlers --- php_phongo.h | 14 +++++ php_phongo_structs.h | 45 ++++++++------ src/BSON/Binary.c | 24 +++++++- src/BSON/Decimal128.c | 24 +++++++- src/BSON/Javascript.c | 24 +++++++- src/BSON/ObjectID.c | 24 +++++++- src/BSON/Regex.c | 24 +++++++- src/BSON/Timestamp.c | 24 +++++++- src/BSON/UTCDateTime.c | 24 +++++++- tests/bson/bug0939-001.phpt | 119 ++++++++++++++++++++++++++++++++++++ 10 files changed, 306 insertions(+), 40 deletions(-) create mode 100644 tests/bson/bug0939-001.phpt diff --git a/php_phongo.h b/php_phongo.h index a9aef0a08..07387f464 100644 --- a/php_phongo.h +++ b/php_phongo.h @@ -167,6 +167,20 @@ zend_bool phongo_writeconcernerror_init(zval *return_value, bson_t *bson TSRMLS_ ce->unserialize = zend_class_unserialize_deny; \ } while(0); +#define PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_debug, intern, props, size) do { \ + if (is_debug) { \ + ALLOC_HASHTABLE(props); \ + zend_hash_init((props), (size), NULL, ZVAL_PTR_DTOR, 0); \ + } else if ((intern)->properties) { \ + zend_hash_clean((intern)->properties); \ + (props) = (intern)->properties; \ + } else { \ + ALLOC_HASHTABLE(props); \ + zend_hash_init((props), (size), NULL, ZVAL_PTR_DTOR, 0); \ + (intern)->properties = (props); \ + } \ +} while(0); + #endif /* PHONGO_H */ diff --git a/php_phongo_structs.h b/php_phongo_structs.h index e67b15153..52ab8f60f 100644 --- a/php_phongo_structs.h +++ b/php_phongo_structs.h @@ -139,24 +139,27 @@ typedef struct { typedef struct { PHONGO_ZEND_OBJECT_PRE - char *data; - int data_len; - uint8_t type; + char *data; + int data_len; + uint8_t type; + HashTable *properties; PHONGO_ZEND_OBJECT_POST } php_phongo_binary_t; typedef struct { PHONGO_ZEND_OBJECT_PRE - bool initialized; - bson_decimal128_t decimal; + bool initialized; + bson_decimal128_t decimal; + HashTable *properties; PHONGO_ZEND_OBJECT_POST } php_phongo_decimal128_t; typedef struct { PHONGO_ZEND_OBJECT_PRE - char *code; - size_t code_len; - bson_t *scope; + char *code; + size_t code_len; + bson_t *scope; + HashTable *properties; PHONGO_ZEND_OBJECT_POST } php_phongo_javascript_t; @@ -172,32 +175,36 @@ typedef struct { typedef struct { PHONGO_ZEND_OBJECT_PRE - bool initialized; - char oid[25]; + bool initialized; + char oid[25]; + HashTable *properties; PHONGO_ZEND_OBJECT_POST } php_phongo_objectid_t; typedef struct { PHONGO_ZEND_OBJECT_PRE - char *pattern; - int pattern_len; - char *flags; - int flags_len; + char *pattern; + int pattern_len; + char *flags; + int flags_len; + HashTable *properties; PHONGO_ZEND_OBJECT_POST } php_phongo_regex_t; typedef struct { PHONGO_ZEND_OBJECT_PRE - bool initialized; - uint32_t increment; - uint32_t timestamp; + bool initialized; + uint32_t increment; + uint32_t timestamp; + HashTable *properties; PHONGO_ZEND_OBJECT_POST } php_phongo_timestamp_t; typedef struct { PHONGO_ZEND_OBJECT_PRE - bool initialized; - int64_t milliseconds; + bool initialized; + int64_t milliseconds; + HashTable *properties; PHONGO_ZEND_OBJECT_POST } php_phongo_utcdatetime_t; diff --git a/src/BSON/Binary.c b/src/BSON/Binary.c index e57d8396f..b3d6cae6b 100644 --- a/src/BSON/Binary.c +++ b/src/BSON/Binary.c @@ -336,6 +336,11 @@ static void php_phongo_binary_free_object(phongo_free_object_arg *object TSRMLS_ efree(intern->data); } + if (intern->properties) { + zend_hash_destroy(intern->properties); + FREE_HASHTABLE(intern->properties); + } + #if PHP_VERSION_ID < 70000 efree(intern); #endif @@ -390,16 +395,17 @@ static HashTable *php_phongo_binary_get_gc(zval *object, phongo_get_gc_table tab *table = NULL; *n = 0; - return zend_std_get_properties(object TSRMLS_CC); + return Z_BINARY_OBJ_P(object)->properties; } /* }}} */ -static HashTable *php_phongo_binary_get_properties(zval *object TSRMLS_DC) /* {{{ */ +static HashTable *php_phongo_binary_get_properties_hash(zval *object, bool is_debug TSRMLS_DC) /* {{{ */ { php_phongo_binary_t *intern; HashTable *props; intern = Z_BINARY_OBJ_P(object); - props = zend_std_get_properties(object TSRMLS_CC); + + PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_debug, intern, props, 2); if (!intern->data) { return props; @@ -431,6 +437,17 @@ static HashTable *php_phongo_binary_get_properties(zval *object TSRMLS_DC) /* {{ return props; } /* }}} */ + +static HashTable *php_phongo_binary_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */ +{ + *is_temp = 1; + return php_phongo_binary_get_properties_hash(object, true TSRMLS_CC); +} /* }}} */ + +static HashTable *php_phongo_binary_get_properties(zval *object TSRMLS_DC) /* {{{ */ +{ + return php_phongo_binary_get_properties_hash(object, false TSRMLS_CC); +} /* }}} */ /* }}} */ void php_phongo_binary_init_ce(INIT_FUNC_ARGS) /* {{{ */ @@ -448,6 +465,7 @@ void php_phongo_binary_init_ce(INIT_FUNC_ARGS) /* {{{ */ memcpy(&php_phongo_handler_binary, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); php_phongo_handler_binary.compare_objects = php_phongo_binary_compare_objects; + php_phongo_handler_binary.get_debug_info = php_phongo_binary_get_debug_info; php_phongo_handler_binary.get_gc = php_phongo_binary_get_gc; php_phongo_handler_binary.get_properties = php_phongo_binary_get_properties; #if PHP_VERSION_ID >= 70000 diff --git a/src/BSON/Decimal128.c b/src/BSON/Decimal128.c index 982bd16e5..2f5f88f57 100644 --- a/src/BSON/Decimal128.c +++ b/src/BSON/Decimal128.c @@ -269,6 +269,11 @@ static void php_phongo_decimal128_free_object(phongo_free_object_arg *object TSR zend_object_std_dtor(&intern->std TSRMLS_CC); + if (intern->properties) { + zend_hash_destroy(intern->properties); + FREE_HASHTABLE(intern->properties); + } + #if PHP_VERSION_ID < 70000 efree(intern); #endif @@ -303,17 +308,18 @@ static HashTable *php_phongo_decimal128_get_gc(zval *object, phongo_get_gc_table *table = NULL; *n = 0; - return zend_std_get_properties(object TSRMLS_CC); + return Z_DECIMAL128_OBJ_P(object)->properties; } /* }}} */ -static HashTable *php_phongo_decimal128_get_properties(zval *object TSRMLS_DC) /* {{{ */ +static HashTable *php_phongo_decimal128_get_properties_hash(zval *object, bool is_debug TSRMLS_DC) /* {{{ */ { php_phongo_decimal128_t *intern; HashTable *props; char outbuf[BSON_DECIMAL128_STRING] = ""; intern = Z_DECIMAL128_OBJ_P(object); - props = zend_std_get_properties(object TSRMLS_CC); + + PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_debug, intern, props, 1); if (!intern->initialized) { return props; @@ -340,6 +346,17 @@ static HashTable *php_phongo_decimal128_get_properties(zval *object TSRMLS_DC) / return props; } /* }}} */ + +static HashTable *php_phongo_decimal128_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */ +{ + *is_temp = 1; + return php_phongo_decimal128_get_properties_hash(object, true TSRMLS_CC); +} /* }}} */ + +static HashTable *php_phongo_decimal128_get_properties(zval *object TSRMLS_DC) /* {{{ */ +{ + return php_phongo_decimal128_get_properties_hash(object, false TSRMLS_CC); +} /* }}} */ /* }}} */ void php_phongo_decimal128_init_ce(INIT_FUNC_ARGS) /* {{{ */ @@ -356,6 +373,7 @@ void php_phongo_decimal128_init_ce(INIT_FUNC_ARGS) /* {{{ */ zend_class_implements(php_phongo_decimal128_ce TSRMLS_CC, 1, zend_ce_serializable); memcpy(&php_phongo_handler_decimal128, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); + php_phongo_handler_decimal128.get_debug_info = php_phongo_decimal128_get_debug_info; php_phongo_handler_decimal128.get_gc = php_phongo_decimal128_get_gc; php_phongo_handler_decimal128.get_properties = php_phongo_decimal128_get_properties; #if PHP_VERSION_ID >= 70000 diff --git a/src/BSON/Javascript.c b/src/BSON/Javascript.c index 57999cc03..fde79f12b 100644 --- a/src/BSON/Javascript.c +++ b/src/BSON/Javascript.c @@ -382,6 +382,11 @@ static void php_phongo_javascript_free_object(phongo_free_object_arg *object TSR intern->scope = NULL; } + if (intern->properties) { + zend_hash_destroy(intern->properties); + FREE_HASHTABLE(intern->properties); + } + #if PHP_VERSION_ID < 70000 efree(intern); #endif @@ -426,16 +431,17 @@ static HashTable *php_phongo_javascript_get_gc(zval *object, phongo_get_gc_table *table = NULL; *n = 0; - return zend_std_get_properties(object TSRMLS_CC); + return Z_JAVASCRIPT_OBJ_P(object)->properties; } /* }}} */ -HashTable *php_phongo_javascript_get_properties(zval *object TSRMLS_DC) /* {{{ */ +HashTable *php_phongo_javascript_get_properties_hash(zval *object, bool is_debug TSRMLS_DC) /* {{{ */ { php_phongo_javascript_t *intern; HashTable *props; intern = Z_JAVASCRIPT_OBJ_P(object); - props = zend_std_get_properties(object TSRMLS_CC); + + PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_debug, intern, props, 2); if (!intern->code) { return props; @@ -504,6 +510,17 @@ HashTable *php_phongo_javascript_get_properties(zval *object TSRMLS_DC) /* {{{ * return props; } /* }}} */ + +static HashTable *php_phongo_javascript_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */ +{ + *is_temp = 1; + return php_phongo_javascript_get_properties_hash(object, true TSRMLS_CC); +} /* }}} */ + +static HashTable *php_phongo_javascript_get_properties(zval *object TSRMLS_DC) /* {{{ */ +{ + return php_phongo_javascript_get_properties_hash(object, false TSRMLS_CC); +} /* }}} */ /* }}} */ void php_phongo_javascript_init_ce(INIT_FUNC_ARGS) /* {{{ */ @@ -521,6 +538,7 @@ void php_phongo_javascript_init_ce(INIT_FUNC_ARGS) /* {{{ */ memcpy(&php_phongo_handler_javascript, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); php_phongo_handler_javascript.compare_objects = php_phongo_javascript_compare_objects; + php_phongo_handler_javascript.get_debug_info = php_phongo_javascript_get_debug_info; php_phongo_handler_javascript.get_gc = php_phongo_javascript_get_gc; php_phongo_handler_javascript.get_properties = php_phongo_javascript_get_properties; #if PHP_VERSION_ID >= 70000 diff --git a/src/BSON/ObjectID.c b/src/BSON/ObjectID.c index 265f54918..f5098d8e6 100644 --- a/src/BSON/ObjectID.c +++ b/src/BSON/ObjectID.c @@ -307,6 +307,11 @@ static void php_phongo_objectid_free_object(phongo_free_object_arg *object TSRML zend_object_std_dtor(&intern->std TSRMLS_CC); + if (intern->properties) { + zend_hash_destroy(intern->properties); + FREE_HASHTABLE(intern->properties); + } + #if PHP_VERSION_ID < 70000 efree(intern); #endif @@ -352,16 +357,17 @@ static HashTable *php_phongo_objectid_get_gc(zval *object, phongo_get_gc_table t *table = NULL; *n = 0; - return zend_std_get_properties(object TSRMLS_CC); + return Z_OBJECTID_OBJ_P(object)->properties; } /* }}} */ -static HashTable *php_phongo_objectid_get_properties(zval *object TSRMLS_DC) /* {{{ */ +static HashTable *php_phongo_objectid_get_properties_hash(zval *object, bool is_debug TSRMLS_DC) /* {{{ */ { php_phongo_objectid_t *intern; HashTable *props; intern = Z_OBJECTID_OBJ_P(object); - props = zend_std_get_properties(object TSRMLS_CC); + + PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_debug, intern, props, 1); if (!intern->oid) { return props; @@ -386,6 +392,17 @@ static HashTable *php_phongo_objectid_get_properties(zval *object TSRMLS_DC) /* return props; } /* }}} */ + +static HashTable *php_phongo_objectid_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */ +{ + *is_temp = 1; + return php_phongo_objectid_get_properties_hash(object, true TSRMLS_CC); +} /* }}} */ + +static HashTable *php_phongo_objectid_get_properties(zval *object TSRMLS_DC) /* {{{ */ +{ + return php_phongo_objectid_get_properties_hash(object, false TSRMLS_CC); +} /* }}} */ /* }}} */ void php_phongo_objectid_init_ce(INIT_FUNC_ARGS) /* {{{ */ @@ -403,6 +420,7 @@ void php_phongo_objectid_init_ce(INIT_FUNC_ARGS) /* {{{ */ memcpy(&php_phongo_handler_objectid, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); php_phongo_handler_objectid.compare_objects = php_phongo_objectid_compare_objects; + php_phongo_handler_objectid.get_debug_info = php_phongo_objectid_get_debug_info; php_phongo_handler_objectid.get_gc = php_phongo_objectid_get_gc; php_phongo_handler_objectid.get_properties = php_phongo_objectid_get_properties; #if PHP_VERSION_ID >= 70000 diff --git a/src/BSON/Regex.c b/src/BSON/Regex.c index 21c91bc4d..e5fbea067 100644 --- a/src/BSON/Regex.c +++ b/src/BSON/Regex.c @@ -344,6 +344,11 @@ static void php_phongo_regex_free_object(phongo_free_object_arg *object TSRMLS_D efree(intern->flags); } + if (intern->properties) { + zend_hash_destroy(intern->properties); + FREE_HASHTABLE(intern->properties); + } + #if PHP_VERSION_ID < 70000 efree(intern); #endif @@ -396,16 +401,17 @@ static HashTable *php_phongo_regex_get_gc(zval *object, phongo_get_gc_table tabl *table = NULL; *n = 0; - return zend_std_get_properties(object TSRMLS_CC); + return Z_REGEX_OBJ_P(object)->properties; } /* }}} */ -static HashTable *php_phongo_regex_get_properties(zval *object TSRMLS_DC) /* {{{ */ +static HashTable *php_phongo_regex_get_properties_hash(zval *object, bool is_debug TSRMLS_DC) /* {{{ */ { php_phongo_regex_t *intern; HashTable *props; intern = Z_REGEX_OBJ_P(object); - props = zend_std_get_properties(object TSRMLS_CC); + + PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_debug, intern, props, 2); if (!intern->pattern) { return props; @@ -437,6 +443,17 @@ static HashTable *php_phongo_regex_get_properties(zval *object TSRMLS_DC) /* {{{ return props; } /* }}} */ + +static HashTable *php_phongo_regex_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */ +{ + *is_temp = 1; + return php_phongo_regex_get_properties_hash(object, true TSRMLS_CC); +} /* }}} */ + +static HashTable *php_phongo_regex_get_properties(zval *object TSRMLS_DC) /* {{{ */ +{ + return php_phongo_regex_get_properties_hash(object, false TSRMLS_CC); +} /* }}} */ /* }}} */ void php_phongo_regex_init_ce(INIT_FUNC_ARGS) /* {{{ */ @@ -454,6 +471,7 @@ void php_phongo_regex_init_ce(INIT_FUNC_ARGS) /* {{{ */ memcpy(&php_phongo_handler_regex, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); php_phongo_handler_regex.compare_objects = php_phongo_regex_compare_objects; + php_phongo_handler_regex.get_debug_info = php_phongo_regex_get_debug_info; php_phongo_handler_regex.get_gc = php_phongo_regex_get_gc; php_phongo_handler_regex.get_properties = php_phongo_regex_get_properties; #if PHP_VERSION_ID >= 70000 diff --git a/src/BSON/Timestamp.c b/src/BSON/Timestamp.c index 64a855723..a6f3ffca1 100644 --- a/src/BSON/Timestamp.c +++ b/src/BSON/Timestamp.c @@ -370,6 +370,11 @@ static void php_phongo_timestamp_free_object(phongo_free_object_arg *object TSRM zend_object_std_dtor(&intern->std TSRMLS_CC); + if (intern->properties) { + zend_hash_destroy(intern->properties); + FREE_HASHTABLE(intern->properties); + } + #if PHP_VERSION_ID < 70000 efree(intern); #endif @@ -423,10 +428,10 @@ static HashTable *php_phongo_timestamp_get_gc(zval *object, phongo_get_gc_table *table = NULL; *n = 0; - return zend_std_get_properties(object TSRMLS_CC); + return Z_TIMESTAMP_OBJ_P(object)->properties; } /* }}} */ -static HashTable *php_phongo_timestamp_get_properties(zval *object TSRMLS_DC) /* {{{ */ +static HashTable *php_phongo_timestamp_get_properties_hash(zval *object, bool is_debug TSRMLS_DC) /* {{{ */ { php_phongo_timestamp_t *intern; HashTable *props; @@ -436,7 +441,8 @@ static HashTable *php_phongo_timestamp_get_properties(zval *object TSRMLS_DC) /* int s_timestamp_len; intern = Z_TIMESTAMP_OBJ_P(object); - props = zend_std_get_properties(object TSRMLS_CC); + + PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_debug, intern, props, 2); if (!intern->initialized) { return props; @@ -471,6 +477,17 @@ static HashTable *php_phongo_timestamp_get_properties(zval *object TSRMLS_DC) /* return props; } /* }}} */ + +static HashTable *php_phongo_timestamp_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */ +{ + *is_temp = 1; + return php_phongo_timestamp_get_properties_hash(object, true TSRMLS_CC); +} /* }}} */ + +static HashTable *php_phongo_timestamp_get_properties(zval *object TSRMLS_DC) /* {{{ */ +{ + return php_phongo_timestamp_get_properties_hash(object, false TSRMLS_CC); +} /* }}} */ /* }}} */ void php_phongo_timestamp_init_ce(INIT_FUNC_ARGS) /* {{{ */ @@ -488,6 +505,7 @@ void php_phongo_timestamp_init_ce(INIT_FUNC_ARGS) /* {{{ */ memcpy(&php_phongo_handler_timestamp, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); php_phongo_handler_timestamp.compare_objects = php_phongo_timestamp_compare_objects; + php_phongo_handler_timestamp.get_debug_info = php_phongo_timestamp_get_debug_info; php_phongo_handler_timestamp.get_gc = php_phongo_timestamp_get_gc; php_phongo_handler_timestamp.get_properties = php_phongo_timestamp_get_properties; #if PHP_VERSION_ID >= 70000 diff --git a/src/BSON/UTCDateTime.c b/src/BSON/UTCDateTime.c index c19e0e4da..4e7632974 100644 --- a/src/BSON/UTCDateTime.c +++ b/src/BSON/UTCDateTime.c @@ -423,6 +423,11 @@ static void php_phongo_utcdatetime_free_object(phongo_free_object_arg *object TS zend_object_std_dtor(&intern->std TSRMLS_CC); + if (intern->properties) { + zend_hash_destroy(intern->properties); + FREE_HASHTABLE(intern->properties); + } + #if PHP_VERSION_ID < 70000 efree(intern); #endif @@ -471,10 +476,10 @@ static HashTable *php_phongo_utcdatetime_get_gc(zval *object, phongo_get_gc_tabl *table = NULL; *n = 0; - return zend_std_get_properties(object TSRMLS_CC); + return Z_UTCDATETIME_OBJ_P(object)->properties; } /* }}} */ -static HashTable *php_phongo_utcdatetime_get_properties(zval *object TSRMLS_DC) /* {{{ */ +static HashTable *php_phongo_utcdatetime_get_properties_hash(zval *object, bool is_debug TSRMLS_DC) /* {{{ */ { php_phongo_utcdatetime_t *intern; HashTable *props; @@ -482,7 +487,8 @@ static HashTable *php_phongo_utcdatetime_get_properties(zval *object TSRMLS_DC) int s_milliseconds_len; intern = Z_UTCDATETIME_OBJ_P(object); - props = zend_std_get_properties(object TSRMLS_CC); + + PHONGO_GET_PROPERTY_HASH_INIT_PROPS(is_debug, intern, props, 2); if (!intern->initialized) { return props; @@ -509,6 +515,17 @@ static HashTable *php_phongo_utcdatetime_get_properties(zval *object TSRMLS_DC) return props; } /* }}} */ + +static HashTable *php_phongo_utcdatetime_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */ +{ + *is_temp = 1; + return php_phongo_utcdatetime_get_properties_hash(object, true TSRMLS_CC); +} /* }}} */ + +static HashTable *php_phongo_utcdatetime_get_properties(zval *object TSRMLS_DC) /* {{{ */ +{ + return php_phongo_utcdatetime_get_properties_hash(object, false TSRMLS_CC); +} /* }}} */ /* }}} */ void php_phongo_utcdatetime_init_ce(INIT_FUNC_ARGS) /* {{{ */ @@ -526,6 +543,7 @@ void php_phongo_utcdatetime_init_ce(INIT_FUNC_ARGS) /* {{{ */ memcpy(&php_phongo_handler_utcdatetime, phongo_get_std_object_handlers(), sizeof(zend_object_handlers)); php_phongo_handler_utcdatetime.compare_objects = php_phongo_utcdatetime_compare_objects; + php_phongo_handler_utcdatetime.get_debug_info = php_phongo_utcdatetime_get_debug_info; php_phongo_handler_utcdatetime.get_gc = php_phongo_utcdatetime_get_gc; php_phongo_handler_utcdatetime.get_properties = php_phongo_utcdatetime_get_properties; #if PHP_VERSION_ID >= 70000 diff --git a/tests/bson/bug0939-001.phpt b/tests/bson/bug0939-001.phpt new file mode 100644 index 000000000..15e5833b5 --- /dev/null +++ b/tests/bson/bug0939-001.phpt @@ -0,0 +1,119 @@ +--TEST-- +PHPC-939: BSON classes should not assign public properties after var_dump() +--FILE-- + 42]), ['code', 'scope'] ], + [ new MongoDB\BSON\MaxKey, [] ], + [ new MongoDB\BSON\MinKey, [] ], + [ new MongoDB\BSON\ObjectID, ['oid'] ], + [ new MongoDB\BSON\Regex('foo', 'i'), ['pattern', 'flags'] ], + [ new MongoDB\BSON\Timestamp(1234, 5678), ['increment', 'timestamp'] ], + [ new MongoDB\BSON\UTCDateTime, ['milliseconds'] ], +]; + +foreach ($tests as $test) { + list($object, $properties) = $test; + + var_dump($object); + + foreach ($properties as $property) { + var_dump($object->{$property}); + } + + echo "\n"; +} + +?> +===DONE=== + +--EXPECTF-- +object(MongoDB\BSON\Binary)#%d (%d) { + ["data"]=> + string(3) "foo" + ["type"]=> + int(0) +} + +Notice: Undefined property: MongoDB\BSON\Binary::$data in %s on line %d +NULL + +Notice: Undefined property: MongoDB\BSON\Binary::$type in %s on line %d +NULL + +object(MongoDB\BSON\Decimal128)#%d (%d) { + ["dec"]=> + string(4) "3.14" +} + +Notice: Undefined property: MongoDB\BSON\Decimal128::$dec in %s on line %d +NULL + +object(MongoDB\BSON\Javascript)#%d (%d) { + ["code"]=> + string(30) "function foo() { return bar; }" + ["scope"]=> + object(stdClass)#%d (%d) { + ["bar"]=> + int(42) + } +} + +Notice: Undefined property: MongoDB\BSON\Javascript::$code in %s on line %d +NULL + +Notice: Undefined property: MongoDB\BSON\Javascript::$scope in %s on line %d +NULL + +object(MongoDB\BSON\MaxKey)#%d (%d) { +} + +object(MongoDB\BSON\MinKey)#%d (%d) { +} + +object(MongoDB\BSON\ObjectID)#%d (%d) { + ["oid"]=> + string(24) "%x" +} + +Notice: Undefined property: MongoDB\BSON\ObjectID::$oid in %s on line %d +NULL + +object(MongoDB\BSON\Regex)#%d (%d) { + ["pattern"]=> + string(3) "foo" + ["flags"]=> + string(1) "i" +} + +Notice: Undefined property: MongoDB\BSON\Regex::$pattern in %s on line %d +NULL + +Notice: Undefined property: MongoDB\BSON\Regex::$flags in %s on line %d +NULL + +object(MongoDB\BSON\Timestamp)#%d (%d) { + ["increment"]=> + string(4) "1234" + ["timestamp"]=> + string(4) "5678" +} + +Notice: Undefined property: MongoDB\BSON\Timestamp::$increment in %s on line %d +NULL + +Notice: Undefined property: MongoDB\BSON\Timestamp::$timestamp in %s on line %d +NULL + +object(MongoDB\BSON\UTCDateTime)#%d (%d) { + ["milliseconds"]=> + string(%d) "%d" +} + +Notice: Undefined property: MongoDB\BSON\UTCDateTime::$milliseconds in %s on line %d +NULL + +===DONE===