Skip to content

Commit 2fe8c4a

Browse files
committed
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2: Fix GH-16261: Reference invariant broken in mb_convert_variables()
2 parents 932406a + bf70d9b commit 2fe8c4a

File tree

3 files changed

+64
-1
lines changed

3 files changed

+64
-1
lines changed

NEWS

+4
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ PHP NEWS
5858
. Fix GH-16136 (Memory leak in php_ldap_do_modify() when entry is not a
5959
proper dictionary). (Girgias)
6060

61+
- MBString:
62+
. Fixed bug GH-16261 (Reference invariant broken in mb_convert_variables()).
63+
(nielsdos)
64+
6165
- OpenSSL:
6266
. Fixed stub for openssl_csr_new. (Jakub Zelenka)
6367

ext/mbstring/mbstring.c

+16-1
Original file line numberDiff line numberDiff line change
@@ -3514,7 +3514,22 @@ static bool mb_recursive_convert_variable(zval *var, const mbfl_encoding* from_e
35143514

35153515
HashTable *ht = HASH_OF(var);
35163516
if (ht != NULL) {
3517-
ZEND_HASH_FOREACH_VAL_IND(ht, entry) {
3517+
ZEND_HASH_FOREACH_VAL(ht, entry) {
3518+
/* Can be a typed property declaration, in which case we need to remove the reference from the source list.
3519+
* Just using ZEND_TRY_ASSIGN_STRINGL is not sufficient because that would not unwrap the reference
3520+
* and change values through references (see bug #26639). */
3521+
if (Z_TYPE_P(entry) == IS_INDIRECT) {
3522+
ZEND_ASSERT(Z_TYPE_P(var) == IS_OBJECT);
3523+
3524+
entry = Z_INDIRECT_P(entry);
3525+
if (Z_ISREF_P(entry) && Z_TYPE_P(Z_REFVAL_P(entry)) == IS_STRING) {
3526+
zend_property_info *info = zend_get_typed_property_info_for_slot(Z_OBJ_P(var), entry);
3527+
if (info) {
3528+
ZEND_REF_DEL_TYPE_SOURCE(Z_REF_P(entry), info);
3529+
}
3530+
}
3531+
}
3532+
35183533
if (mb_recursive_convert_variable(entry, from_encoding, to_encoding)) {
35193534
if (Z_REFCOUNTED_P(var)) {
35203535
Z_UNPROTECT_RECURSION_P(var);

ext/mbstring/tests/gh16261.phpt

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
--TEST--
2+
GH-16261 (Reference invariant broken in mb_convert_variables())
3+
--EXTENSIONS--
4+
mbstring
5+
--FILE--
6+
<?php
7+
class Test {
8+
public string $x;
9+
public string $y;
10+
public array $z;
11+
}
12+
$test = new Test;
13+
$ref = "hello";
14+
$ref2 = "world";
15+
$ref3 = [&$ref2];
16+
$test->x =& $ref;
17+
$test->z =& $ref3;
18+
mb_convert_variables("EUC-JP", "Shift_JIS", $test);
19+
20+
class Test2 {
21+
public function __construct(public string $x) {}
22+
}
23+
$test2 = new Test2("foo");
24+
25+
mb_convert_variables("EUC-JP", "Shift_JIS", $test->x);
26+
27+
var_dump($test, $test2);
28+
?>
29+
--EXPECT--
30+
object(Test)#1 (2) {
31+
["x"]=>
32+
string(5) "hello"
33+
["y"]=>
34+
uninitialized(string)
35+
["z"]=>
36+
&array(1) {
37+
[0]=>
38+
string(5) "world"
39+
}
40+
}
41+
object(Test2)#2 (1) {
42+
["x"]=>
43+
string(3) "foo"
44+
}

0 commit comments

Comments
 (0)