@@ -3530,7 +3530,8 @@ PHP_FUNCTION(mb_convert_variables)
3530
3530
size_t elistsz ;
3531
3531
const mbfl_encoding * * elist ;
3532
3532
char * to_enc ;
3533
- void * ptmp ;
3533
+ void * ptmp ;
3534
+ int recursion_error = 0 ;
3534
3535
3535
3536
if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "sZ+" , & to_enc , & to_enc_len , & zfrom_enc , & args , & argc ) == FAILURE ) {
3536
3537
return ;
@@ -3593,6 +3594,11 @@ PHP_FUNCTION(mb_convert_variables)
3593
3594
target_hash = HASH_OF (* var );
3594
3595
if (target_hash != NULL ) {
3595
3596
while (zend_hash_get_current_data (target_hash , (void * * ) & hash_entry ) != FAILURE ) {
3597
+ if (++ target_hash -> nApplyCount > 1 ) {
3598
+ -- target_hash -> nApplyCount ;
3599
+ recursion_error = 1 ;
3600
+ goto detect_end ;
3601
+ }
3596
3602
zend_hash_move_forward (target_hash );
3597
3603
if (Z_TYPE_PP (hash_entry ) == IS_ARRAY || Z_TYPE_PP (hash_entry ) == IS_OBJECT ) {
3598
3604
if (stack_level >= stack_max ) {
@@ -3629,6 +3635,20 @@ PHP_FUNCTION(mb_convert_variables)
3629
3635
from_encoding = mbfl_encoding_detector_judge2 (identd );
3630
3636
mbfl_encoding_detector_delete (identd );
3631
3637
}
3638
+ if (recursion_error ) {
3639
+ while (stack_level -- && (var = stack [stack_level ])) {
3640
+ if (HASH_OF (* var )-> nApplyCount > 1 ) {
3641
+ HASH_OF (* var )-> nApplyCount -- ;
3642
+ }
3643
+ }
3644
+ efree (stack );
3645
+ efree (args );
3646
+ if (elist != NULL ) {
3647
+ efree ((void * )elist );
3648
+ }
3649
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Cannot handle recursive references" );
3650
+ RETURN_FALSE ;
3651
+ }
3632
3652
efree (stack );
3633
3653
3634
3654
if (!from_encoding ) {
@@ -3676,6 +3696,11 @@ PHP_FUNCTION(mb_convert_variables)
3676
3696
while (zend_hash_get_current_data (target_hash , (void * * ) & hash_entry ) != FAILURE ) {
3677
3697
zend_hash_move_forward (target_hash );
3678
3698
if (Z_TYPE_PP (hash_entry ) == IS_ARRAY || Z_TYPE_PP (hash_entry ) == IS_OBJECT ) {
3699
+ if (++ (HASH_OF (* hash_entry )-> nApplyCount ) > 1 ) {
3700
+ -- (HASH_OF (* hash_entry )-> nApplyCount );
3701
+ recursion_error = 1 ;
3702
+ goto conv_end ;
3703
+ }
3679
3704
if (stack_level >= stack_max ) {
3680
3705
stack_max += PHP_MBSTR_STACK_BLOCK_SIZE ;
3681
3706
ptmp = erealloc (stack , sizeof (zval * * )* stack_max );
@@ -3684,7 +3709,6 @@ PHP_FUNCTION(mb_convert_variables)
3684
3709
stack [stack_level ] = var ;
3685
3710
stack_level ++ ;
3686
3711
var = hash_entry ;
3687
- SEPARATE_ZVAL (hash_entry );
3688
3712
target_hash = HASH_OF (* var );
3689
3713
if (target_hash != NULL ) {
3690
3714
zend_hash_internal_pointer_reset (target_hash );
@@ -3701,25 +3725,38 @@ PHP_FUNCTION(mb_convert_variables)
3701
3725
} else {
3702
3726
zval_dtor (* hash_entry );
3703
3727
}
3704
- ZVAL_STRINGL (* hash_entry , (char * )ret -> val , ret -> len , 0 );
3728
+ ZVAL_STRINGL (* hash_entry , (char * )ret -> val , ret -> len , 0 );
3729
+ }
3705
3730
}
3706
3731
}
3707
3732
}
3708
- }
3709
- } else if (Z_TYPE_PP (var ) == IS_STRING ) {
3710
- string .val = (unsigned char * )Z_STRVAL_PP (var );
3711
- string .len = Z_STRLEN_PP (var );
3712
- ret = mbfl_buffer_converter_feed_result (convd , & string , & result );
3713
- if (ret != NULL ) {
3714
- zval_dtor (* var );
3715
- ZVAL_STRINGL (* var , (char * )ret -> val , ret -> len , 0 );
3733
+ } else if (Z_TYPE_PP (var ) == IS_STRING ) {
3734
+ string .val = (unsigned char * )Z_STRVAL_PP (var );
3735
+ string .len = Z_STRLEN_PP (var );
3736
+ ret = mbfl_buffer_converter_feed_result (convd , & string , & result );
3737
+ if (ret != NULL ) {
3738
+ zval_dtor (* var );
3739
+ ZVAL_STRINGL (* var , (char * )ret -> val , ret -> len , 0 );
3716
3740
}
3717
3741
}
3718
3742
}
3719
- efree (stack );
3720
3743
3744
+ conv_end :
3721
3745
MBSTRG (illegalchars ) += mbfl_buffer_illegalchars (convd );
3722
3746
mbfl_buffer_converter_delete (convd );
3747
+
3748
+ if (recursion_error ) {
3749
+ while (stack_level -- && (var = stack [stack_level ])) {
3750
+ if (HASH_OF (* var )-> nApplyCount > 1 ) {
3751
+ HASH_OF (* var )-> nApplyCount -- ;
3752
+ }
3753
+ }
3754
+ efree (stack );
3755
+ efree (args );
3756
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Cannot handle recursive references" );
3757
+ RETURN_FALSE ;
3758
+ }
3759
+ efree (stack );
3723
3760
}
3724
3761
3725
3762
efree (args );
0 commit comments