Skip to content

Commit 96e59a2

Browse files
author
Yasuo Ohgaki
committed
Merge branch 'PHP-7.1'
* PHP-7.1: Fixed Bug #66964 mb_convert_variables() cannot detect recursion
2 parents 2605cee + 012232b commit 96e59a2

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
@@ -3862,6 +3862,7 @@ PHP_FUNCTION(mb_convert_variables)
38623862
const mbfl_encoding **elist;
38633863
char *to_enc;
38643864
void *ptmp;
3865+
int recursion_error = 0;
38653866

38663867
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz+", &to_enc, &to_enc_len, &zfrom_enc, &args, &argc) == FAILURE) {
38673868
return;
@@ -3926,6 +3927,11 @@ PHP_FUNCTION(mb_convert_variables)
39263927
target_hash = HASH_OF(var);
39273928
if (target_hash != NULL) {
39283929
while ((hash_entry = zend_hash_get_current_data(target_hash)) != NULL) {
3930+
if (++target_hash->u.v.nApplyCount > 1) {
3931+
--target_hash->u.v.nApplyCount;
3932+
recursion_error = 1;
3933+
goto detect_end;
3934+
}
39293935
zend_hash_move_forward(target_hash);
39303936
if (Z_TYPE_P(hash_entry) == IS_INDIRECT) {
39313937
hash_entry = Z_INDIRECT_P(hash_entry);
@@ -3966,6 +3972,19 @@ PHP_FUNCTION(mb_convert_variables)
39663972
from_encoding = mbfl_encoding_detector_judge2(identd);
39673973
mbfl_encoding_detector_delete(identd);
39683974
}
3975+
if (recursion_error) {
3976+
while(stack_level-- && (var = &stack[stack_level])) {
3977+
if (HASH_OF(var)->u.v.nApplyCount > 1) {
3978+
HASH_OF(var)->u.v.nApplyCount--;
3979+
}
3980+
}
3981+
efree(stack);
3982+
if (elist != NULL) {
3983+
efree((void *)elist);
3984+
}
3985+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot handle recursive references");
3986+
RETURN_FALSE;
3987+
}
39693988
efree(stack);
39703989

39713990
if (!from_encoding) {
@@ -4020,6 +4039,11 @@ PHP_FUNCTION(mb_convert_variables)
40204039
hash_entry = hash_entry_ptr;
40214040
ZVAL_DEREF(hash_entry);
40224041
if (Z_TYPE_P(hash_entry) == IS_ARRAY || Z_TYPE_P(hash_entry) == IS_OBJECT) {
4042+
if (++(HASH_OF(hash_entry)->u.v.nApplyCount) > 1) {
4043+
--(HASH_OF(hash_entry)->u.v.nApplyCount);
4044+
recursion_error = 1;
4045+
goto conv_end;
4046+
}
40234047
if (stack_level >= stack_max) {
40244048
stack_max += PHP_MBSTR_STACK_BLOCK_SIZE;
40254049
ptmp = erealloc(stack, sizeof(zval) * stack_max);
@@ -4059,10 +4083,22 @@ PHP_FUNCTION(mb_convert_variables)
40594083
}
40604084
}
40614085
}
4062-
efree(stack);
40634086

4087+
conv_end:
40644088
MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd);
40654089
mbfl_buffer_converter_delete(convd);
4090+
4091+
if (recursion_error) {
4092+
while(stack_level-- && (var = &stack[stack_level])) {
4093+
if (HASH_OF(var)->u.v.nApplyCount > 1) {
4094+
HASH_OF(var)->u.v.nApplyCount--;
4095+
}
4096+
}
4097+
efree(stack);
4098+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot handle recursive references");
4099+
RETURN_FALSE;
4100+
}
4101+
efree(stack);
40664102
}
40674103

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