Skip to content

Commit 012232b

Browse files
author
Yasuo Ohgaki
committed
Merge branch 'PHP-7.0' into PHP-7.1
* PHP-7.0: Fixed Bug #66964 mb_convert_variables() cannot detect recursion
2 parents 608decf + 6f1a52b commit 012232b

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
@@ -3728,6 +3728,7 @@ PHP_FUNCTION(mb_convert_variables)
37283728
const mbfl_encoding **elist;
37293729
char *to_enc;
37303730
void *ptmp;
3731+
int recursion_error = 0;
37313732

37323733
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz+", &to_enc, &to_enc_len, &zfrom_enc, &args, &argc) == FAILURE) {
37333734
return;
@@ -3792,6 +3793,11 @@ PHP_FUNCTION(mb_convert_variables)
37923793
target_hash = HASH_OF(var);
37933794
if (target_hash != NULL) {
37943795
while ((hash_entry = zend_hash_get_current_data(target_hash)) != NULL) {
3796+
if (++target_hash->u.v.nApplyCount > 1) {
3797+
--target_hash->u.v.nApplyCount;
3798+
recursion_error = 1;
3799+
goto detect_end;
3800+
}
37953801
zend_hash_move_forward(target_hash);
37963802
if (Z_TYPE_P(hash_entry) == IS_INDIRECT) {
37973803
hash_entry = Z_INDIRECT_P(hash_entry);
@@ -3832,6 +3838,19 @@ PHP_FUNCTION(mb_convert_variables)
38323838
from_encoding = mbfl_encoding_detector_judge2(identd);
38333839
mbfl_encoding_detector_delete(identd);
38343840
}
3841+
if (recursion_error) {
3842+
while(stack_level-- && (var = &stack[stack_level])) {
3843+
if (HASH_OF(var)->u.v.nApplyCount > 1) {
3844+
HASH_OF(var)->u.v.nApplyCount--;
3845+
}
3846+
}
3847+
efree(stack);
3848+
if (elist != NULL) {
3849+
efree((void *)elist);
3850+
}
3851+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot handle recursive references");
3852+
RETURN_FALSE;
3853+
}
38353854
efree(stack);
38363855

38373856
if (!from_encoding) {
@@ -3886,6 +3905,11 @@ PHP_FUNCTION(mb_convert_variables)
38863905
hash_entry = hash_entry_ptr;
38873906
ZVAL_DEREF(hash_entry);
38883907
if (Z_TYPE_P(hash_entry) == IS_ARRAY || Z_TYPE_P(hash_entry) == IS_OBJECT) {
3908+
if (++(HASH_OF(hash_entry)->u.v.nApplyCount) > 1) {
3909+
--(HASH_OF(hash_entry)->u.v.nApplyCount);
3910+
recursion_error = 1;
3911+
goto conv_end;
3912+
}
38893913
if (stack_level >= stack_max) {
38903914
stack_max += PHP_MBSTR_STACK_BLOCK_SIZE;
38913915
ptmp = erealloc(stack, sizeof(zval) * stack_max);
@@ -3925,10 +3949,22 @@ PHP_FUNCTION(mb_convert_variables)
39253949
}
39263950
}
39273951
}
3928-
efree(stack);
39293952

3953+
conv_end:
39303954
MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd);
39313955
mbfl_buffer_converter_delete(convd);
3956+
3957+
if (recursion_error) {
3958+
while(stack_level-- && (var = &stack[stack_level])) {
3959+
if (HASH_OF(var)->u.v.nApplyCount > 1) {
3960+
HASH_OF(var)->u.v.nApplyCount--;
3961+
}
3962+
}
3963+
efree(stack);
3964+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot handle recursive references");
3965+
RETURN_FALSE;
3966+
}
3967+
efree(stack);
39323968
}
39333969

39343970
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)