@@ -532,10 +532,29 @@ static zend_result php_json_escape_string(
532532}
533533/* }}} */
534534
535+ #define PHP_JSON_SERIALIZABLE_OBJECT_PROTECT_RECURSION (_obj , _ht ) \
536+ do { \
537+ if (UNEXPECTED(_ht)) { \
538+ GC_PROTECT_RECURSION(_ht); \
539+ } else { \
540+ GC_PROTECT_RECURSION(_obj); \
541+ } \
542+ } while (0)
543+
544+ #define PHP_JSON_SERIALIZABLE_OBJECT_UNPROTECT_RECURSION (_obj , _ht ) \
545+ do { \
546+ if (UNEXPECTED(_ht)) { \
547+ GC_UNPROTECT_RECURSION(_ht); \
548+ } else { \
549+ GC_UNPROTECT_RECURSION(_obj); \
550+ } \
551+ } while (0)
552+
535553static zend_result php_json_encode_serializable_object (smart_str * buf , zval * val , int options , php_json_encoder * encoder ) /* {{{ */
536554{
537555 zend_class_entry * ce = Z_OBJCE_P (val );
538- HashTable * myht = Z_OBJPROP_P (val );
556+ zend_object * obj = Z_OBJ_P (val );
557+ HashTable * myht = GC_IS_RECURSIVE (obj ) ? Z_OBJPROP_P (val ) : NULL ;
539558 zval retval , fname ;
540559 zend_result return_code ;
541560
@@ -547,7 +566,7 @@ static zend_result php_json_encode_serializable_object(smart_str *buf, zval *val
547566 return FAILURE ;
548567 }
549568
550- PHP_JSON_HASH_PROTECT_RECURSION ( myht );
569+ PHP_JSON_SERIALIZABLE_OBJECT_PROTECT_RECURSION ( obj , myht );
551570
552571 ZVAL_STRING (& fname , "jsonSerialize" );
553572
@@ -560,7 +579,7 @@ static zend_result php_json_encode_serializable_object(smart_str *buf, zval *val
560579 if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR ) {
561580 smart_str_appendl (buf , "null" , 4 );
562581 }
563- PHP_JSON_HASH_UNPROTECT_RECURSION ( myht );
582+ PHP_JSON_SERIALIZABLE_OBJECT_UNPROTECT_RECURSION ( obj , myht );
564583 return FAILURE ;
565584 }
566585
@@ -572,19 +591,19 @@ static zend_result php_json_encode_serializable_object(smart_str *buf, zval *val
572591 if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR ) {
573592 smart_str_appendl (buf , "null" , 4 );
574593 }
575- PHP_JSON_HASH_UNPROTECT_RECURSION ( myht );
594+ PHP_JSON_SERIALIZABLE_OBJECT_UNPROTECT_RECURSION ( obj , myht );
576595 return FAILURE ;
577596 }
578597
579598 if ((Z_TYPE (retval ) == IS_OBJECT ) &&
580599 (Z_OBJ (retval ) == Z_OBJ_P (val ))) {
581600 /* Handle the case where jsonSerialize does: return $this; by going straight to encode array */
582- PHP_JSON_HASH_UNPROTECT_RECURSION ( myht );
601+ PHP_JSON_SERIALIZABLE_OBJECT_UNPROTECT_RECURSION ( obj , myht );
583602 return_code = php_json_encode_array (buf , & retval , options , encoder );
584603 } else {
585604 /* All other types, encode as normal */
586605 return_code = php_json_encode_zval (buf , & retval , options , encoder );
587- PHP_JSON_HASH_UNPROTECT_RECURSION ( myht );
606+ PHP_JSON_SERIALIZABLE_OBJECT_UNPROTECT_RECURSION ( obj , myht );
588607 }
589608
590609 zval_ptr_dtor (& retval );
0 commit comments