Skip to content

Commit b525a9b

Browse files
committed
Merge pull request #481
2 parents bf64016 + 1297538 commit b525a9b

File tree

3 files changed

+66
-15
lines changed

3 files changed

+66
-15
lines changed

phongo_compat.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,10 @@
167167
# define Z_ISUNDEF(x) !x
168168
# define phongo_free_object_arg void
169169
# define phongo_zpp_char_len int
170-
# define ZEND_HASH_APPLY_COUNT(ht) (ht)->nApplyCount
170+
# define ZEND_HASH_APPLY_PROTECTION(ht) true
171+
# define ZEND_HASH_GET_APPLY_COUNT(ht) ((ht)->nApplyCount)
172+
# define ZEND_HASH_DEC_APPLY_COUNT(ht) ((ht)->nApplyCount -= 1)
173+
# define ZEND_HASH_INC_APPLY_COUNT(ht) ((ht)->nApplyCount += 1)
171174
# define PHONGO_RETVAL_STRINGL(s, slen) RETVAL_STRINGL(s, slen, 1)
172175
# define PHONGO_RETURN_STRINGL(s, slen) RETURN_STRINGL(s, slen, 1)
173176
# define PHONGO_RETURN_STRING(s) RETURN_STRING(s, 1)

src/bson.c

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -862,8 +862,8 @@ void object_to_bson(zval *object, php_phongo_bson_flags_t flags, const char *key
862862
tmp_ht = HASH_OF(obj_data);
863863
#endif
864864

865-
if (tmp_ht) {
866-
ZEND_HASH_APPLY_COUNT(tmp_ht)++;
865+
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
866+
ZEND_HASH_INC_APPLY_COUNT(tmp_ht);
867867
}
868868

869869
/* Persistable objects must always be serialized as BSON documents;
@@ -897,8 +897,8 @@ void object_to_bson(zval *object, php_phongo_bson_flags_t flags, const char *key
897897
bson_append_array_end(bson, &child);
898898
}
899899

900-
if (tmp_ht) {
901-
ZEND_HASH_APPLY_COUNT(tmp_ht)--;
900+
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
901+
ZEND_HASH_DEC_APPLY_COUNT(tmp_ht);
902902
}
903903
zval_ptr_dtor(&obj_data);
904904
return;
@@ -970,12 +970,22 @@ void object_to_bson(zval *object, php_phongo_bson_flags_t flags, const char *key
970970
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC, "Unexpected %s instance: %s", php_phongo_type_ce->name, Z_OBJCE_P(object)->name);
971971
#endif
972972
return;
973-
}
973+
} else {
974+
HashTable *tmp_ht = HASH_OF(object);
975+
976+
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
977+
ZEND_HASH_INC_APPLY_COUNT(tmp_ht);
978+
}
974979

975-
mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding document");
976-
bson_append_document_begin(bson, key, key_len, &child);
977-
phongo_zval_to_bson(object, flags, &child, NULL TSRMLS_CC);
978-
bson_append_document_end(bson, &child);
980+
mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding document");
981+
bson_append_document_begin(bson, key, key_len, &child);
982+
phongo_zval_to_bson(object, flags, &child, NULL TSRMLS_CC);
983+
bson_append_document_end(bson, &child);
984+
985+
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
986+
ZEND_HASH_DEC_APPLY_COUNT(tmp_ht);
987+
}
988+
}
979989
}
980990

981991
static void phongo_bson_append(bson_t *bson, php_phongo_bson_flags_t flags, const char *key, long key_len, zval *entry TSRMLS_DC)
@@ -1023,16 +1033,16 @@ static void phongo_bson_append(bson_t *bson, php_phongo_bson_flags_t flags, cons
10231033
bson_t child;
10241034
HashTable *tmp_ht = HASH_OF(entry);
10251035

1026-
if (tmp_ht) {
1027-
ZEND_HASH_APPLY_COUNT(tmp_ht)++;
1036+
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
1037+
ZEND_HASH_INC_APPLY_COUNT(tmp_ht);
10281038
}
10291039

10301040
bson_append_array_begin(bson, key, key_len, &child);
10311041
phongo_zval_to_bson(entry, flags, &child, NULL TSRMLS_CC);
10321042
bson_append_array_end(bson, &child);
10331043

1034-
if (tmp_ht) {
1035-
ZEND_HASH_APPLY_COUNT(tmp_ht)--;
1044+
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
1045+
ZEND_HASH_DEC_APPLY_COUNT(tmp_ht);
10361046
}
10371047
break;
10381048
}
@@ -1191,7 +1201,7 @@ PHONGO_API void phongo_zval_to_bson(zval *data, php_phongo_bson_flags_t flags, b
11911201
return;
11921202
}
11931203

1194-
if (!ht_data || ZEND_HASH_APPLY_COUNT(ht_data) > 1) {
1204+
if (!ht_data || ZEND_HASH_GET_APPLY_COUNT(ht_data) > 1) {
11951205
#if PHP_VERSION_ID >= 70000
11961206
if (Z_TYPE_P(data) == IS_OBJECT && instanceof_function(Z_OBJCE_P(data), php_phongo_serializable_ce TSRMLS_CC)) {
11971207
#endif

tests/bson/bson-fromPHP-004.phpt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
BSON\fromPHP(): PHP documents with circular references
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/tools.php';
7+
8+
echo "\nTesting packed array with circular reference\n";
9+
10+
$document = ['x' => 1, 'y' => []];
11+
$document['y'][] = &$document['y'];
12+
echo toJson(fromPHP($document)), "\n";
13+
14+
echo "\nTesting associative array with circular reference\n";
15+
16+
$document = ['x' => 1, 'y' => []];
17+
$document['y']['z'] = &$document['y'];
18+
echo toJson(fromPHP($document)), "\n";
19+
20+
echo "\nTesting object with circular reference\n";
21+
22+
$document = (object) ['x' => 1, 'y' => (object) []];
23+
$document->y->z = &$document->y;
24+
echo toJson(fromPHP($document)), "\n";
25+
26+
?>
27+
===DONE===
28+
<?php exit(0); ?>
29+
--EXPECTF--
30+
Testing packed array with circular reference
31+
{ "x" : 1, "y" : [ [ ] ] }
32+
33+
Testing associative array with circular reference
34+
{ "x" : 1, "y" : { "z" : { } } }
35+
36+
Testing object with circular reference
37+
{ "x" : 1, "y" : { "z" : { } } }
38+
===DONE===

0 commit comments

Comments
 (0)