From: Yasuo Ohgaki Date: Tue, 6 Sep 2016 07:41:52 +0000 (+0900) Subject: Merge branch 'PHP-5.6' into PHP-7.0 X-Git-Tag: php-7.1.0RC2~56^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6f1a52bfbb5e7f0c5bf353f24531e582bc00ab18;p=php Merge branch 'PHP-5.6' into PHP-7.0 * PHP-5.6: Fixed Bug #66964 mb_convert_variables() cannot detect recursion --- 6f1a52bfbb5e7f0c5bf353f24531e582bc00ab18 diff --cc ext/mbstring/mbstring.c index c9200b8ce5,18e348ddae..baec14c70c --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@@ -3701,8 -3531,9 +3701,9 @@@ PHP_FUNCTION(mb_convert_variables const mbfl_encoding **elist; char *to_enc; void *ptmp; + int recursion_error = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sZ+", &to_enc, &to_enc_len, &zfrom_enc, &args, &argc) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz+", &to_enc, &to_enc_len, &zfrom_enc, &args, &argc) == FAILURE) { return; } @@@ -3759,27 -3588,28 +3760,32 @@@ } } else { stack_level--; - var = stack[stack_level]; + var = &stack[stack_level]; } - if (Z_TYPE_PP(var) == IS_ARRAY || Z_TYPE_PP(var) == IS_OBJECT) { - target_hash = HASH_OF(*var); + if (Z_TYPE_P(var) == IS_ARRAY || Z_TYPE_P(var) == IS_OBJECT) { + target_hash = HASH_OF(var); if (target_hash != NULL) { - while (zend_hash_get_current_data(target_hash, (void **) &hash_entry) != FAILURE) { - if (++target_hash->nApplyCount > 1) { - --target_hash->nApplyCount; + while ((hash_entry = zend_hash_get_current_data(target_hash)) != NULL) { ++ if (++target_hash->u.v.nApplyCount > 1) { ++ --target_hash->u.v.nApplyCount; + recursion_error = 1; + goto detect_end; + } zend_hash_move_forward(target_hash); - if (Z_TYPE_PP(hash_entry) == IS_ARRAY || Z_TYPE_PP(hash_entry) == IS_OBJECT) { + if (Z_TYPE_P(hash_entry) == IS_INDIRECT) { + hash_entry = Z_INDIRECT_P(hash_entry); + } + ZVAL_DEREF(hash_entry); + if (Z_TYPE_P(hash_entry) == IS_ARRAY || Z_TYPE_P(hash_entry) == IS_OBJECT) { if (stack_level >= stack_max) { stack_max += PHP_MBSTR_STACK_BLOCK_SIZE; - ptmp = erealloc(stack, sizeof(zval **)*stack_max); - stack = (zval ***)ptmp; + ptmp = erealloc(stack, sizeof(zval) * stack_max); + stack = (zval *)ptmp; } - stack[stack_level] = var; + ZVAL_COPY_VALUE(&stack[stack_level], var); stack_level++; var = hash_entry; - target_hash = HASH_OF(*var); + target_hash = HASH_OF(var); if (target_hash != NULL) { zend_hash_internal_pointer_reset(target_hash); continue; @@@ -3805,6 -3635,20 +3811,19 @@@ detect_end from_encoding = mbfl_encoding_detector_judge2(identd); mbfl_encoding_detector_delete(identd); } + if (recursion_error) { - while(stack_level-- && (var = stack[stack_level])) { - if (HASH_OF(*var)->nApplyCount > 1) { - HASH_OF(*var)->nApplyCount--; ++ while(stack_level-- && (var = &stack[stack_level])) { ++ if (HASH_OF(var)->u.v.nApplyCount > 1) { ++ HASH_OF(var)->u.v.nApplyCount--; + } + } + efree(stack); - efree(args); + if (elist != NULL) { + efree((void *)elist); + } + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot handle recursive references"); + RETURN_FALSE; + } efree(stack); if (!from_encoding) { @@@ -3846,29 -3688,28 +3865,34 @@@ } } else { stack_level--; - var = stack[stack_level]; + var = &stack[stack_level]; } - if (Z_TYPE_PP(var) == IS_ARRAY || Z_TYPE_PP(var) == IS_OBJECT) { - target_hash = HASH_OF(*var); + if (Z_TYPE_P(var) == IS_ARRAY || Z_TYPE_P(var) == IS_OBJECT) { + target_hash = HASH_OF(var); if (target_hash != NULL) { - while (zend_hash_get_current_data(target_hash, (void **) &hash_entry) != FAILURE) { + while ((hash_entry_ptr = zend_hash_get_current_data(target_hash)) != NULL) { zend_hash_move_forward(target_hash); - if (Z_TYPE_PP(hash_entry) == IS_ARRAY || Z_TYPE_PP(hash_entry) == IS_OBJECT) { - if (++(HASH_OF(*hash_entry)->nApplyCount) > 1) { - --(HASH_OF(*hash_entry)->nApplyCount); + if (Z_TYPE_P(hash_entry_ptr) == IS_INDIRECT) { + hash_entry_ptr = Z_INDIRECT_P(hash_entry_ptr); + } + hash_entry = hash_entry_ptr; + ZVAL_DEREF(hash_entry); + if (Z_TYPE_P(hash_entry) == IS_ARRAY || Z_TYPE_P(hash_entry) == IS_OBJECT) { ++ if (++(HASH_OF(hash_entry)->u.v.nApplyCount) > 1) { ++ --(HASH_OF(hash_entry)->u.v.nApplyCount); + recursion_error = 1; + goto conv_end; + } if (stack_level >= stack_max) { stack_max += PHP_MBSTR_STACK_BLOCK_SIZE; - ptmp = erealloc(stack, sizeof(zval **)*stack_max); - stack = (zval ***)ptmp; + ptmp = erealloc(stack, sizeof(zval) * stack_max); + stack = (zval *)ptmp; } - stack[stack_level] = var; + ZVAL_COPY_VALUE(&stack[stack_level], var); stack_level++; var = hash_entry; - target_hash = HASH_OF(*var); + SEPARATE_ZVAL(hash_entry); + target_hash = HASH_OF(var); if (target_hash != NULL) { zend_hash_internal_pointer_reset(target_hash); continue; @@@ -3898,14 -3740,29 +3922,26 @@@ } } } - efree(stack); + conv_end: MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd); mbfl_buffer_converter_delete(convd); + + if (recursion_error) { - while(stack_level-- && (var = stack[stack_level])) { - if (HASH_OF(*var)->nApplyCount > 1) { - HASH_OF(*var)->nApplyCount--; ++ while(stack_level-- && (var = &stack[stack_level])) { ++ if (HASH_OF(var)->u.v.nApplyCount > 1) { ++ HASH_OF(var)->u.v.nApplyCount--; + } + } + efree(stack); - efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot handle recursive references"); + RETURN_FALSE; + } + efree(stack); } - efree(args); - if (from_encoding) { - RETURN_STRING(from_encoding->name, 1); + RETURN_STRING(from_encoding->name); } else { RETURN_FALSE; }