Skip to content

Commit 197f3f7

Browse files
committed
PHPC-1166: Update zend array recursion protection for PHP 7.3
1 parent af675fc commit 197f3f7

File tree

3 files changed

+59
-17
lines changed

3 files changed

+59
-17
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

0 commit comments

Comments
 (0)