Skip to content

Commit 6f1a52b

Browse files
author
Yasuo Ohgaki
committed
Merge branch 'PHP-5.6' into PHP-7.0
* PHP-5.6: Fixed Bug #66964 mb_convert_variables() cannot detect recursion
2 parents 81ec843 + a25f6f8 commit 6f1a52b

File tree

2 files changed

+90
-1
lines changed

2 files changed

+90
-1
lines changed

ext/mbstring/mbstring.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3701,6 +3701,7 @@ PHP_FUNCTION(mb_convert_variables)
37013701
const mbfl_encoding **elist;
37023702
char *to_enc;
37033703
void *ptmp;
3704+
int recursion_error = 0;
37043705

37053706
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz+", &to_enc, &to_enc_len, &zfrom_enc, &args, &argc) == FAILURE) {
37063707
return;
@@ -3765,6 +3766,11 @@ PHP_FUNCTION(mb_convert_variables)
37653766
target_hash = HASH_OF(var);
37663767
if (target_hash != NULL) {
37673768
while ((hash_entry = zend_hash_get_current_data(target_hash)) != NULL) {
3769+
if (++target_hash->u.v.nApplyCount > 1) {
3770+
--target_hash->u.v.nApplyCount;
3771+
recursion_error = 1;
3772+
goto detect_end;
3773+
}
37683774
zend_hash_move_forward(target_hash);
37693775
if (Z_TYPE_P(hash_entry) == IS_INDIRECT) {
37703776
hash_entry = Z_INDIRECT_P(hash_entry);
@@ -3805,6 +3811,19 @@ PHP_FUNCTION(mb_convert_variables)
38053811
from_encoding = mbfl_encoding_detector_judge2(identd);
38063812
mbfl_encoding_detector_delete(identd);
38073813
}
3814+
if (recursion_error) {
3815+
while(stack_level-- && (var = &stack[stack_level])) {
3816+
if (HASH_OF(var)->u.v.nApplyCount > 1) {
3817+
HASH_OF(var)->u.v.nApplyCount--;
3818+
}
3819+
}
3820+
efree(stack);
3821+
if (elist != NULL) {
3822+
efree((void *)elist);
3823+
}
3824+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot handle recursive references");
3825+
RETURN_FALSE;
3826+
}
38083827
efree(stack);
38093828

38103829
if (!from_encoding) {
@@ -3859,6 +3878,11 @@ PHP_FUNCTION(mb_convert_variables)
38593878
hash_entry = hash_entry_ptr;
38603879
ZVAL_DEREF(hash_entry);
38613880
if (Z_TYPE_P(hash_entry) == IS_ARRAY || Z_TYPE_P(hash_entry) == IS_OBJECT) {
3881+
if (++(HASH_OF(hash_entry)->u.v.nApplyCount) > 1) {
3882+
--(HASH_OF(hash_entry)->u.v.nApplyCount);
3883+
recursion_error = 1;
3884+
goto conv_end;
3885+
}
38623886
if (stack_level >= stack_max) {
38633887
stack_max += PHP_MBSTR_STACK_BLOCK_SIZE;
38643888
ptmp = erealloc(stack, sizeof(zval) * stack_max);
@@ -3898,10 +3922,22 @@ PHP_FUNCTION(mb_convert_variables)
38983922
}
38993923
}
39003924
}
3901-
efree(stack);
39023925

3926+
conv_end:
39033927
MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd);
39043928
mbfl_buffer_converter_delete(convd);
3929+
3930+
if (recursion_error) {
3931+
while(stack_level-- && (var = &stack[stack_level])) {
3932+
if (HASH_OF(var)->u.v.nApplyCount > 1) {
3933+
HASH_OF(var)->u.v.nApplyCount--;
3934+
}
3935+
}
3936+
efree(stack);
3937+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot handle recursive references");
3938+
RETURN_FALSE;
3939+
}
3940+
efree(stack);
39053941
}
39063942

39073943
if (from_encoding) {

ext/mbstring/tests/bug66964.phpt

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
--TEST--
2+
Bug #66964 (mb_convert_variables() cannot detect recursion)
3+
--SKIPIF--
4+
<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?>
5+
--FILE--
6+
<?php
7+
$a[] = &$a;
8+
var_dump(mb_convert_variables('utf-8', 'auto', $a));
9+
var_dump(mb_convert_variables('utf-8', 'utf-8', $a));
10+
11+
unset($a);
12+
$a[] = '日本語テキスト';
13+
$a[] = '日本語テキスト';
14+
$a[] = '日本語テキスト';
15+
$a[] = '日本語テキスト';
16+
var_dump(mb_convert_variables('utf-8', 'utf-8', $a), $a);
17+
18+
$a[] = &$a;
19+
var_dump(mb_convert_variables('utf-8', 'utf-8', $a), $a);
20+
21+
?>
22+
--EXPECTF--
23+
Warning: mb_convert_variables(): %s on line %d
24+
bool(false)
25+
26+
Warning: mb_convert_variables(): %s on line %d
27+
bool(false)
28+
string(5) "UTF-8"
29+
array(4) {
30+
[0]=>
31+
string(21) "日本語テキスト"
32+
[1]=>
33+
string(21) "日本語テキスト"
34+
[2]=>
35+
string(21) "日本語テキスト"
36+
[3]=>
37+
string(21) "日本語テキスト"
38+
}
39+
40+
Warning: mb_convert_variables(): %s on line %d
41+
bool(false)
42+
array(5) {
43+
[0]=>
44+
string(21) "日本語テキスト"
45+
[1]=>
46+
string(21) "日本語テキスト"
47+
[2]=>
48+
string(21) "日本語テキスト"
49+
[3]=>
50+
string(21) "日本語テキスト"
51+
[4]=>
52+
*RECURSION*
53+
}

0 commit comments

Comments
 (0)