Skip to content

Commit f32410b

Browse files
committed
Extend zend guards to allow recursion protection
1 parent 0fd226c commit f32410b

File tree

4 files changed

+30
-13
lines changed

4 files changed

+30
-13
lines changed

Zend/zend_API.c

+1
Original file line numberDiff line numberDiff line change
@@ -2746,6 +2746,7 @@ ZEND_API void zend_add_magic_method(zend_class_entry *ce, zend_function *fptr, z
27462746
ce->__tostring = fptr;
27472747
} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
27482748
ce->__debugInfo = fptr;
2749+
ce->ce_flags |= ZEND_ACC_USE_GUARDS;
27492750
} else if (zend_string_equals_literal(lcname, "__serialize")) {
27502751
ce->__serialize = fptr;
27512752
} else if (zend_string_equals_literal(lcname, "__unserialize")) {

Zend/zend_object_handlers.c

+10-10
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@
3636
#define ZEND_WRONG_PROPERTY_OFFSET 0
3737

3838
/* guard flags */
39-
#define IN_GET (1<<0)
40-
#define IN_SET (1<<1)
41-
#define IN_UNSET (1<<2)
42-
#define IN_ISSET (1<<3)
39+
#define IN_GET ZEND_GUARD_PROPERTY_GET
40+
#define IN_SET ZEND_GUARD_PROPERTY_SET
41+
#define IN_UNSET ZEND_GUARD_PROPERTY_UNSET
42+
#define IN_ISSET ZEND_GUARD_PROPERTY_ISSET
4343

4444
/*
4545
__X accessors explanation:
@@ -555,17 +555,17 @@ ZEND_API uint32_t *zend_get_property_guard(zend_object *zobj, zend_string *membe
555555
if (EXPECTED(str == member) ||
556556
/* str and member don't necessarily have a pre-calculated hash value here */
557557
EXPECTED(zend_string_equal_content(str, member))) {
558-
return &Z_PROPERTY_GUARD_P(zv);
559-
} else if (EXPECTED(Z_PROPERTY_GUARD_P(zv) == 0)) {
558+
return &Z_GUARD_P(zv);
559+
} else if (EXPECTED(Z_GUARD_P(zv) == 0)) {
560560
zval_ptr_dtor_str(zv);
561561
ZVAL_STR_COPY(zv, member);
562-
return &Z_PROPERTY_GUARD_P(zv);
562+
return &Z_GUARD_P(zv);
563563
} else {
564564
ALLOC_HASHTABLE(guards);
565565
zend_hash_init(guards, 8, NULL, zend_property_guard_dtor, 0);
566566
/* mark pointer as "special" using low bit */
567567
zend_hash_add_new_ptr(guards, str,
568-
(void*)(((uintptr_t)&Z_PROPERTY_GUARD_P(zv)) | 1));
568+
(void*)(((uintptr_t)&Z_GUARD_P(zv)) | 1));
569569
zval_ptr_dtor_str(zv);
570570
ZVAL_ARR(zv, guards);
571571
}
@@ -579,8 +579,8 @@ ZEND_API uint32_t *zend_get_property_guard(zend_object *zobj, zend_string *membe
579579
} else {
580580
ZEND_ASSERT(Z_TYPE_P(zv) == IS_UNDEF);
581581
ZVAL_STR_COPY(zv, member);
582-
Z_PROPERTY_GUARD_P(zv) = 0;
583-
return &Z_PROPERTY_GUARD_P(zv);
582+
Z_GUARD_P(zv) &= ~ZEND_GUARD_PROPERTY_MASK;
583+
return &Z_GUARD_P(zv);
584584
}
585585
/* we have to allocate uint32_t separately because ht->arData may be reallocated */
586586
ptr = (uint32_t*)emalloc(sizeof(uint32_t));

Zend/zend_types.h

+12-3
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ struct _zval_struct {
345345
uint32_t num_args; /* arguments number for EX(This) */
346346
uint32_t fe_pos; /* foreach position */
347347
uint32_t fe_iter_idx; /* foreach iterator index */
348-
uint32_t property_guard; /* single property guard */
348+
uint32_t guard; /* recursion and single property guard */
349349
uint32_t constant_flags; /* constant flags */
350350
uint32_t extra; /* not further specified */
351351
} u2;
@@ -619,6 +619,15 @@ struct _zend_ast_ref {
619619
#define _IS_BOOL 18
620620
#define _IS_NUMBER 19
621621

622+
/* guard flags */
623+
#define ZEND_GUARD_PROPERTY_GET (1<<0)
624+
#define ZEND_GUARD_PROPERTY_SET (1<<1)
625+
#define ZEND_GUARD_PROPERTY_UNSET (1<<2)
626+
#define ZEND_GUARD_PROPERTY_ISSET (1<<3)
627+
#define ZEND_GUARD_PROPERTY_MASK 15
628+
#define ZEND_GUARD_RECURSION_DEBUG (1<<4)
629+
#define ZEND_GUARD_RECURSION_JSON (1<<5)
630+
622631
static zend_always_inline uint8_t zval_get_type(const zval* pz) {
623632
return pz->u1.v.type;
624633
}
@@ -659,8 +668,8 @@ static zend_always_inline uint8_t zval_get_type(const zval* pz) {
659668
#define Z_FE_ITER(zval) (zval).u2.fe_iter_idx
660669
#define Z_FE_ITER_P(zval_p) Z_FE_ITER(*(zval_p))
661670

662-
#define Z_PROPERTY_GUARD(zval) (zval).u2.property_guard
663-
#define Z_PROPERTY_GUARD_P(zval_p) Z_PROPERTY_GUARD(*(zval_p))
671+
#define Z_GUARD(zval) (zval).u2.guard
672+
#define Z_GUARD_P(zval_p) Z_GUARD(*(zval_p))
664673

665674
#define Z_CONSTANT_FLAGS(zval) (zval).u2.constant_flags
666675
#define Z_CONSTANT_FLAGS_P(zval_p) Z_CONSTANT_FLAGS(*(zval_p))

ext/json/json.c

+7
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,17 @@ PHP_JSON_API zend_class_entry *php_json_exception_ce;
3737

3838
PHP_JSON_API ZEND_DECLARE_MODULE_GLOBALS(json)
3939

40+
static int php_json_implement_json_serializable(zend_class_entry *interface, zend_class_entry *class_type)
41+
{
42+
class_type->ce_flags |= ZEND_ACC_USE_GUARDS;
43+
return SUCCESS;
44+
}
45+
4046
/* {{{ MINIT */
4147
static PHP_MINIT_FUNCTION(json)
4248
{
4349
php_json_serializable_ce = register_class_JsonSerializable();
50+
php_json_serializable_ce->interface_gets_implemented = php_json_implement_json_serializable;
4451

4552
php_json_exception_ce = register_class_JsonException(zend_ce_exception);
4653

0 commit comments

Comments
 (0)