Skip to content

Commit d681e70

Browse files
committed
Merged pull request #835
2 parents af675fc + 98e583b commit d681e70

11 files changed

+89
-47
lines changed

phongo_compat.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,58 @@ void phongo_add_exception_prop(const char* prop, int prop_len, zval* value TSRML
3232
}
3333
}
3434

35+
#ifdef ZEND_HASH_GET_APPLY_COUNT /* PHP 7.2 or earlier recursion protection */
36+
inline zend_bool php_phongo_zend_hash_apply_protection_begin(HashTable* ht)
37+
{
38+
if (!ht) {
39+
return 1;
40+
}
41+
if (ZEND_HASH_GET_APPLY_COUNT(ht) > 0) {
42+
return 0;
43+
}
44+
if (ZEND_HASH_APPLY_PROTECTION(ht)) {
45+
ZEND_HASH_INC_APPLY_COUNT(ht);
46+
}
47+
return 1;
48+
}
49+
50+
inline zend_bool php_phongo_zend_hash_apply_protection_end(HashTable* ht)
51+
{
52+
if (!ht) {
53+
return 1;
54+
}
55+
if (ZEND_HASH_GET_APPLY_COUNT(ht) == 0) {
56+
return 0;
57+
}
58+
if (ZEND_HASH_APPLY_PROTECTION(ht)) {
59+
ZEND_HASH_DEC_APPLY_COUNT(ht);
60+
}
61+
return 1;
62+
}
63+
#else /* PHP 7.3 or later */
64+
inline zend_bool php_phongo_zend_hash_apply_protection_begin(zend_array* ht)
65+
{
66+
if (GC_IS_RECURSIVE(ht)) {
67+
return 0;
68+
}
69+
if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) {
70+
GC_PROTECT_RECURSION(ht);
71+
}
72+
return 1;
73+
}
74+
75+
inline zend_bool php_phongo_zend_hash_apply_protection_end(zend_array* ht)
76+
{
77+
if (!GC_IS_RECURSIVE(ht)) {
78+
return 0;
79+
}
80+
if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) {
81+
GC_UNPROTECT_RECURSION(ht);
82+
}
83+
return 1;
84+
}
85+
#endif
86+
3587
/*
3688
* Local variables:
3789
* tab-width: 4

phongo_compat.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,9 @@
178178
#error Unsupported architecture (integers are neither 32-bit nor 64-bit)
179179
#endif
180180

181-
void phongo_add_exception_prop(const char* prop, int prop_len, zval* value TSRMLS_DC);
181+
void phongo_add_exception_prop(const char* prop, int prop_len, zval* value TSRMLS_DC);
182+
zend_bool php_phongo_zend_hash_apply_protection_begin(HashTable* ht);
183+
zend_bool php_phongo_zend_hash_apply_protection_end(HashTable* ht);
182184

183185
#endif /* PHONGO_COMPAT_H */
184186

src/bson-encode.c

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -353,53 +353,41 @@ static void php_phongo_bson_append(bson_t* bson, php_phongo_field_path* field_pa
353353
bson_t child;
354354
HashTable* tmp_ht = HASH_OF(entry);
355355

356-
if (tmp_ht && ZEND_HASH_GET_APPLY_COUNT(tmp_ht) > 0) {
356+
if (!php_phongo_zend_hash_apply_protection_begin(tmp_ht)) {
357357
char* path_string = php_phongo_field_path_as_string(field_path);
358358
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC, "Detected recursion for field path \"%s\"", path_string);
359359
efree(path_string);
360360
break;
361361
}
362362

363-
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
364-
ZEND_HASH_INC_APPLY_COUNT(tmp_ht);
365-
}
366-
367363
bson_append_array_begin(bson, key, key_len, &child);
368364
php_phongo_field_path_write_type_at_current_level(field_path, PHONGO_FIELD_PATH_ITEM_ARRAY);
369365
field_path->size++;
370366
php_phongo_zval_to_bson_internal(entry, field_path, flags, &child, NULL TSRMLS_CC);
371367
field_path->size--;
372368
bson_append_array_end(bson, &child);
373369

374-
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
375-
ZEND_HASH_DEC_APPLY_COUNT(tmp_ht);
376-
}
370+
php_phongo_zend_hash_apply_protection_end(tmp_ht);
377371
break;
378372
}
379373
PHONGO_BREAK_INTENTIONALLY_MISSING
380374

381375
case IS_OBJECT: {
382376
HashTable* tmp_ht = HASH_OF(entry);
383377

384-
if (tmp_ht && ZEND_HASH_GET_APPLY_COUNT(tmp_ht) > 0) {
378+
if (!php_phongo_zend_hash_apply_protection_begin(tmp_ht)) {
385379
char* path_string = php_phongo_field_path_as_string(field_path);
386380
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC, "Detected recursion for field path \"%s\"", path_string);
387381
efree(path_string);
388382
break;
389383
}
390384

391-
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
392-
ZEND_HASH_INC_APPLY_COUNT(tmp_ht);
393-
}
394-
395385
php_phongo_field_path_write_type_at_current_level(field_path, PHONGO_FIELD_PATH_ITEM_DOCUMENT);
396386
field_path->size++;
397387
php_phongo_bson_append_object(bson, field_path, flags, key, key_len, entry TSRMLS_CC);
398388
field_path->size--;
399389

400-
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
401-
ZEND_HASH_DEC_APPLY_COUNT(tmp_ht);
402-
}
390+
php_phongo_zend_hash_apply_protection_end(tmp_ht);
403391
break;
404392
}
405393

tests/bson/bson-fromPHP_error-001.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,15 @@ foreach ($invalidValues as $invalidValue) {
4848
--EXPECTF--
4949
Testing top-level objects
5050
Expected MyDocument::bsonSerialize() to return an array or stdClass, %r(null|NULL)%r given
51-
Expected MyDocument::bsonSerialize() to return an array or stdClass, integer given
51+
Expected MyDocument::bsonSerialize() to return an array or stdClass, int%S given
5252
Expected MyDocument::bsonSerialize() to return an array or stdClass, string given
53-
Expected MyDocument::bsonSerialize() to return an array or stdClass, boolean given
53+
Expected MyDocument::bsonSerialize() to return an array or stdClass, bool%S given
5454
Expected MyDocument::bsonSerialize() to return an array or stdClass, MyDocument given
5555

5656
Testing nested objects
5757
Expected MyDocument::bsonSerialize() to return an array or stdClass, %r(null|NULL)%r given
58-
Expected MyDocument::bsonSerialize() to return an array or stdClass, integer given
58+
Expected MyDocument::bsonSerialize() to return an array or stdClass, int%S given
5959
Expected MyDocument::bsonSerialize() to return an array or stdClass, string given
60-
Expected MyDocument::bsonSerialize() to return an array or stdClass, boolean given
60+
Expected MyDocument::bsonSerialize() to return an array or stdClass, bool%S given
6161
Expected MyDocument::bsonSerialize() to return an array or stdClass, MyDocument given
6262
===DONE===

tests/bson/bson-timestamp_error-006.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Expected increment to be an unsigned 32-bit integer or string, %r(null|NULL)%r g
2828
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
2929
Expected increment to be an unsigned 32-bit integer or string, %r(double|float)%r given
3030
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
31-
Expected increment to be an unsigned 32-bit integer or string, boolean given
31+
Expected increment to be an unsigned 32-bit integer or string, bool%S given
3232
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
3333
Expected increment to be an unsigned 32-bit integer or string, array given
3434
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
@@ -38,7 +38,7 @@ Expected timestamp to be an unsigned 32-bit integer or string, %r(null|NULL)%r g
3838
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
3939
Expected timestamp to be an unsigned 32-bit integer or string, %r(double|float)%r given
4040
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
41-
Expected timestamp to be an unsigned 32-bit integer or string, boolean given
41+
Expected timestamp to be an unsigned 32-bit integer or string, bool%S given
4242
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
4343
Expected timestamp to be an unsigned 32-bit integer or string, array given
4444
OK: Got MongoDB\Driver\Exception\InvalidArgumentException

tests/bson/bson-utcdatetime_error-004.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ foreach ($invalidValues as $invalidValue) {
1919
?>
2020
===DONE===
2121
<?php exit(0); ?>
22-
--EXPECT--
22+
--EXPECTF--
2323
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
24-
Expected integer or string, boolean given
24+
Expected integer or string, bool%S given
2525
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
2626
Expected integer or string, array given
2727
===DONE===

tests/bulk/bulkwrite-delete_error-001.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ echo throws(function() use ($bulk) {
1414
?>
1515
===DONE===
1616
<?php exit(0); ?>
17-
--EXPECT--
17+
--EXPECTF--
1818
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
19-
Expected "collation" option to be array or object, integer given
19+
Expected "collation" option to be array or object, int%S given
2020
===DONE===

tests/bulk/bulkwrite-update_error-003.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ echo throws(function() use ($bulk) {
2222
?>
2323
===DONE===
2424
<?php exit(0); ?>
25-
--EXPECT--
25+
--EXPECTF--
2626
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
2727
Replacement document conflicts with true "multi" option
2828

2929
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
30-
Expected "collation" option to be array or object, integer given
30+
Expected "collation" option to be array or object, int%S given
3131

3232
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
33-
Expected "collation" option to be array or object, integer given
33+
Expected "collation" option to be array or object, int%S given
3434
===DONE===

tests/query/query-ctor_error-001.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ foreach ($tests as $test) {
2525
<?php exit(0); ?>
2626
--EXPECTF--
2727
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
28-
Expected "readConcern" option to be MongoDB\Driver\ReadConcern, integer given
28+
Expected "readConcern" option to be MongoDB\Driver\ReadConcern, int%S given
2929
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
3030
Expected "readConcern" option to be MongoDB\Driver\ReadConcern, %r(double|float)%r given
3131
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
3232
Expected "readConcern" option to be MongoDB\Driver\ReadConcern, string given
3333
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
34-
Expected "readConcern" option to be MongoDB\Driver\ReadConcern, boolean given
34+
Expected "readConcern" option to be MongoDB\Driver\ReadConcern, bool%S given
3535
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
3636
Expected "readConcern" option to be MongoDB\Driver\ReadConcern, array given
3737
OK: Got MongoDB\Driver\Exception\InvalidArgumentException

tests/query/query-ctor_error-002.phpt

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,44 +30,44 @@ foreach ($tests as $options) {
3030
?>
3131
===DONE===
3232
<?php exit(0); ?>
33-
--EXPECT--
33+
--EXPECTF--
3434
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
35-
Expected "modifiers" option to be array, integer given
35+
Expected "modifiers" option to be array, int%S given
3636

3737
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
38-
Expected "collation" option to be array or object, integer given
38+
Expected "collation" option to be array or object, int%S given
3939

4040
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
41-
Expected "comment" option to be string, integer given
41+
Expected "comment" option to be string, int%S given
4242

4343
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
44-
Expected "hint" option to be string, array, or object, integer given
44+
Expected "hint" option to be string, array, or object, int%S given
4545

4646
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
47-
Expected "max" option to be array or object, integer given
47+
Expected "max" option to be array or object, int%S given
4848

4949
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
50-
Expected "min" option to be array or object, integer given
50+
Expected "min" option to be array or object, int%S given
5151

5252
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
53-
Expected "projection" option to be array or object, integer given
53+
Expected "projection" option to be array or object, int%S given
5454

5555
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
56-
Expected "sort" option to be array or object, integer given
56+
Expected "sort" option to be array or object, int%S given
5757

5858
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
59-
Expected "$comment" modifier to be string, integer given
59+
Expected "$comment" modifier to be string, int%S given
6060

6161
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
62-
Expected "$hint" modifier to be string, array, or object, integer given
62+
Expected "$hint" modifier to be string, array, or object, int%S given
6363

6464
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
65-
Expected "$max" modifier to be array or object, integer given
65+
Expected "$max" modifier to be array or object, int%S given
6666

6767
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
68-
Expected "$min" modifier to be array or object, integer given
68+
Expected "$min" modifier to be array or object, int%S given
6969

7070
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
71-
Expected "$orderby" modifier to be array or object, integer given
71+
Expected "$orderby" modifier to be array or object, int%S given
7272

7373
===DONE===

0 commit comments

Comments
 (0)