Skip to content

Commit 1799327

Browse files
committed
Merge branch 'PHP-8.1' into PHP-8.2
* PHP-8.1: Fix GH-11028: Heap Buffer Overflow in zval_undefined_cv.
2 parents edd4980 + fc32d39 commit 1799327

File tree

5 files changed

+93
-1
lines changed

5 files changed

+93
-1
lines changed

NEWS

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ PHP NEWS
1010
array is contained in the second). (ilutov)
1111
. Fixed bug GH-10737 (PHP 8.1.16 segfaults on line 597 of
1212
sapi/apache2handler/sapi_apache2.c). (nielsdos, ElliotNB)
13+
. Fixed bug GH-11028 (Heap Buffer Overflow in zval_undefined_cv.). (nielsdos)
1314

1415
- DOM:
1516
. Fixed bug #80602 (Segfault when using DOMChildNode::before()).

Zend/tests/generators/gh11028_1.phpt

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
GH-11028 (Heap Buffer Overflow in zval_undefined_cv with generators) - other types variant
3+
--FILE--
4+
<?php
5+
function generator($x) {
6+
try {
7+
yield $x => 0;
8+
} finally {
9+
return [];
10+
}
11+
}
12+
13+
function test($msg, $x) {
14+
echo "yield $msg\n";
15+
try {
16+
var_dump([...generator($x)]);
17+
} catch (Throwable $e) {
18+
echo $e->getMessage(), "\n";
19+
}
20+
}
21+
22+
test("null", null);
23+
test("false", false);
24+
test("true", true);
25+
test("object", new stdClass);
26+
?>
27+
--EXPECT--
28+
yield null
29+
Keys must be of type int|string during array unpacking
30+
yield false
31+
Keys must be of type int|string during array unpacking
32+
yield true
33+
Keys must be of type int|string during array unpacking
34+
yield object
35+
Keys must be of type int|string during array unpacking

Zend/tests/generators/gh11028_2.phpt

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
GH-11028 (Heap Buffer Overflow in zval_undefined_cv with generators) - original variant
3+
--FILE--
4+
<?php
5+
$c = (function () {
6+
[
7+
...($r = (function () {
8+
try {
9+
yield $a => 0;
10+
} finally {
11+
return [];
12+
}
13+
})()),
14+
];
15+
})()[0];
16+
?>
17+
--EXPECTF--
18+
Warning: Undefined variable $a in %s on line %d
19+
20+
Fatal error: Uncaught Error: Keys must be of type int|string during array unpacking in %s:%d
21+
Stack trace:
22+
#0 %s(%d): {closure}()
23+
#1 {main}
24+
thrown in %s on line %d

Zend/tests/generators/gh11028_3.phpt

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
GH-11028 (Heap Buffer Overflow in zval_undefined_cv with generators) - throw in finally variant
3+
--FILE--
4+
<?php
5+
function generator() {
6+
try {
7+
yield null => 0;
8+
} finally {
9+
throw new Exception("exception");
10+
return [];
11+
}
12+
}
13+
14+
try {
15+
var_dump([...generator()]);
16+
} catch (Throwable $e) {
17+
echo $e->getMessage(), "\n";
18+
}
19+
?>
20+
--EXPECT--
21+
exception

Zend/zend_generators.c

+12-1
Original file line numberDiff line numberDiff line change
@@ -279,14 +279,25 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
279279
ZEND_CALL_VAR(ex, ex->func->op_array.opcodes[try_catch->finally_end].op1.var);
280280

281281
zend_generator_cleanup_unfinished_execution(generator, ex, try_catch->finally_op);
282-
Z_OBJ_P(fast_call) = EG(exception);
282+
zend_object *old_exception = EG(exception);
283+
const zend_op *old_opline_before_exception = EG(opline_before_exception);
283284
EG(exception) = NULL;
285+
Z_OBJ_P(fast_call) = NULL;
284286
Z_OPLINE_NUM_P(fast_call) = (uint32_t)-1;
285287

286288
ex->opline = &ex->func->op_array.opcodes[try_catch->finally_op];
287289
generator->flags |= ZEND_GENERATOR_FORCED_CLOSE;
288290
zend_generator_resume(generator);
289291

292+
if (old_exception) {
293+
EG(opline_before_exception) = old_opline_before_exception;
294+
if (EG(exception)) {
295+
zend_exception_set_previous(EG(exception), old_exception);
296+
} else {
297+
EG(exception) = old_exception;
298+
}
299+
}
300+
290301
/* TODO: If we hit another yield inside try/finally,
291302
* should we also jump to the next finally block? */
292303
break;

0 commit comments

Comments
 (0)