Skip to content

Commit 7790ee8

Browse files
authored
Fix concat_function use-after-free on out-of-memory error (#11297)
Introduced by GH-10049
1 parent 5c74164 commit 7790ee8

File tree

2 files changed

+23
-2
lines changed

2 files changed

+23
-2
lines changed

Zend/tests/bug79836_4.phpt

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Bug #79836 (use-after-free in concat_function)
3+
--INI--
4+
memory_limit=10M
5+
--FILE--
6+
<?php
7+
class Foo {
8+
public function __toString() {
9+
return str_repeat('a', 10);
10+
}
11+
}
12+
13+
$i = str_repeat('a', 5 * 1024 * 1024);
14+
$e = new Foo();
15+
$e .= $i;
16+
?>
17+
--EXPECTF--
18+
Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d

Zend/zend_operators.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -2048,13 +2048,16 @@ has_op2_string:;
20482048
}
20492049

20502050
if (result == op1) {
2051+
/* special case, perform operations on result */
2052+
result_str = zend_string_extend(op1_string, result_len, 0);
2053+
/* Free result after zend_string_extend(), as it may throw an out-of-memory error. If we
2054+
* free it before we would leave the released variable on the stack with shutdown trying
2055+
* to free it again. */
20512056
if (free_op1_string) {
20522057
/* op1_string will be used as the result, so we should not free it */
20532058
i_zval_ptr_dtor(result);
20542059
free_op1_string = false;
20552060
}
2056-
/* special case, perform operations on result */
2057-
result_str = zend_string_extend(op1_string, result_len, 0);
20582061
/* account for the case where result_str == op1_string == op2_string and the realloc is done */
20592062
if (op1_string == op2_string) {
20602063
if (free_op2_string) {

0 commit comments

Comments
 (0)