1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Merge branch 'PHP-8.5'

* PHP-8.5:
  Fix GH-20352: UAF in php_output_handler_free via re-entrant ob_start() during error deactivation
This commit is contained in:
Niels Dossche
2025-12-19 19:37:16 +01:00
2 changed files with 33 additions and 4 deletions

View File

@@ -187,8 +187,12 @@ PHPAPI void php_output_deactivate(void)
/* release all output handlers */
if (OG(handlers).elements) {
while ((handler = zend_stack_top(&OG(handlers)))) {
php_output_handler_free(handler);
zend_stack_del_top(&OG(handlers));
/* It's possible to start a new output handler and mark it as active,
* however this loop will destroy all active handlers. */
OG(active) = NULL;
ZEND_ASSERT(OG(running) == NULL && "output is deactivated therefore running should stay NULL");
php_output_handler_free(handler);
}
}
zend_stack_destroy(&OG(handlers));
@@ -718,10 +722,11 @@ PHPAPI void php_output_handler_dtor(php_output_handler *handler)
* Destroy and free an output handler */
PHPAPI void php_output_handler_free(php_output_handler **h)
{
if (*h) {
php_output_handler_dtor(*h);
efree(*h);
php_output_handler *handler = *h;
if (handler) {
*h = NULL;
php_output_handler_dtor(handler);
efree(handler);
}
}
/* }}} */

24
tests/output/gh20352.phpt Normal file
View File

@@ -0,0 +1,24 @@
--TEST--
GH-20352 (UAF in php_output_handler_free via re-entrant ob_start() during error deactivation)
--FILE--
<?php
class Test {
public function __destruct() {
// Spray output stack
for ($i = 0; $i < 1000; $i++)
ob_start(static function() {});
}
public function __invoke($x) {
// Trigger php_output_deactivate() through forbidden operation
ob_start('foo');
return $x;
}
}
ob_start(new Test, 1);
echo "trigger bug";
?>
--EXPECTF--
Fatal error: ob_start(): Cannot use output buffering in output buffering display handlers in %s on line %d