mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Fix GH-11028: Heap Buffer Overflow in zval_undefined_cv.
For analysis see https://github.com/php/php-src/issues/11028#issuecomment-1508460440 Closes GH-11083.
This commit is contained in:
parent
2eeff96df5
commit
fc32d39b7f
5 changed files with 93 additions and 1 deletions
1
NEWS
1
NEWS
|
@ -10,6 +10,7 @@ PHP NEWS
|
|||
array is contained in the second). (ilutov)
|
||||
. Fixed bug GH-10737 (PHP 8.1.16 segfaults on line 597 of
|
||||
sapi/apache2handler/sapi_apache2.c). (nielsdos, ElliotNB)
|
||||
. Fixed bug GH-11028 (Heap Buffer Overflow in zval_undefined_cv.). (nielsdos)
|
||||
|
||||
- DOM:
|
||||
. Fixed bug #80602 (Segfault when using DOMChildNode::before()).
|
||||
|
|
35
Zend/tests/generators/gh11028_1.phpt
Normal file
35
Zend/tests/generators/gh11028_1.phpt
Normal file
|
@ -0,0 +1,35 @@
|
|||
--TEST--
|
||||
GH-11028 (Heap Buffer Overflow in zval_undefined_cv with generators) - other types variant
|
||||
--FILE--
|
||||
<?php
|
||||
function generator($x) {
|
||||
try {
|
||||
yield $x => 0;
|
||||
} finally {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function test($msg, $x) {
|
||||
echo "yield $msg\n";
|
||||
try {
|
||||
var_dump([...generator($x)]);
|
||||
} catch (Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
}
|
||||
|
||||
test("null", null);
|
||||
test("false", false);
|
||||
test("true", true);
|
||||
test("object", new stdClass);
|
||||
?>
|
||||
--EXPECT--
|
||||
yield null
|
||||
Keys must be of type int|string during array unpacking
|
||||
yield false
|
||||
Keys must be of type int|string during array unpacking
|
||||
yield true
|
||||
Keys must be of type int|string during array unpacking
|
||||
yield object
|
||||
Keys must be of type int|string during array unpacking
|
24
Zend/tests/generators/gh11028_2.phpt
Normal file
24
Zend/tests/generators/gh11028_2.phpt
Normal file
|
@ -0,0 +1,24 @@
|
|||
--TEST--
|
||||
GH-11028 (Heap Buffer Overflow in zval_undefined_cv with generators) - original variant
|
||||
--FILE--
|
||||
<?php
|
||||
$c = (function () {
|
||||
[
|
||||
...($r = (function () {
|
||||
try {
|
||||
yield $a => 0;
|
||||
} finally {
|
||||
return [];
|
||||
}
|
||||
})()),
|
||||
];
|
||||
})()[0];
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: Undefined variable $a in %s on line %d
|
||||
|
||||
Fatal error: Uncaught Error: Keys must be of type int|string during array unpacking in %s:%d
|
||||
Stack trace:
|
||||
#0 %s(%d): {closure}()
|
||||
#1 {main}
|
||||
thrown in %s on line %d
|
21
Zend/tests/generators/gh11028_3.phpt
Normal file
21
Zend/tests/generators/gh11028_3.phpt
Normal file
|
@ -0,0 +1,21 @@
|
|||
--TEST--
|
||||
GH-11028 (Heap Buffer Overflow in zval_undefined_cv with generators) - throw in finally variant
|
||||
--FILE--
|
||||
<?php
|
||||
function generator() {
|
||||
try {
|
||||
yield null => 0;
|
||||
} finally {
|
||||
throw new Exception("exception");
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
var_dump([...generator()]);
|
||||
} catch (Throwable $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
exception
|
|
@ -279,14 +279,25 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
|
|||
ZEND_CALL_VAR(ex, ex->func->op_array.opcodes[try_catch->finally_end].op1.var);
|
||||
|
||||
zend_generator_cleanup_unfinished_execution(generator, ex, try_catch->finally_op);
|
||||
Z_OBJ_P(fast_call) = EG(exception);
|
||||
zend_object *old_exception = EG(exception);
|
||||
const zend_op *old_opline_before_exception = EG(opline_before_exception);
|
||||
EG(exception) = NULL;
|
||||
Z_OBJ_P(fast_call) = NULL;
|
||||
Z_OPLINE_NUM_P(fast_call) = (uint32_t)-1;
|
||||
|
||||
ex->opline = &ex->func->op_array.opcodes[try_catch->finally_op];
|
||||
generator->flags |= ZEND_GENERATOR_FORCED_CLOSE;
|
||||
zend_generator_resume(generator);
|
||||
|
||||
if (old_exception) {
|
||||
EG(opline_before_exception) = old_opline_before_exception;
|
||||
if (EG(exception)) {
|
||||
zend_exception_set_previous(EG(exception), old_exception);
|
||||
} else {
|
||||
EG(exception) = old_exception;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: If we hit another yield inside try/finally,
|
||||
* should we also jump to the next finally block? */
|
||||
break;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue