Skip to content

Commit 77eedd7

Browse files
committed
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
2 parents 46e55dd + c35224e commit 77eedd7

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

main/output.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,12 @@ PHPAPI void php_output_deactivate(void)
187187
/* release all output handlers */
188188
if (OG(handlers).elements) {
189189
while ((handler = zend_stack_top(&OG(handlers)))) {
190-
php_output_handler_free(handler);
191190
zend_stack_del_top(&OG(handlers));
191+
/* It's possible to start a new output handler and mark it as active,
192+
* however this loop will destroy all active handlers. */
193+
OG(active) = NULL;
194+
ZEND_ASSERT(OG(running) == NULL && "output is deactivated therefore running should stay NULL");
195+
php_output_handler_free(handler);
192196
}
193197
}
194198
zend_stack_destroy(&OG(handlers));
@@ -718,10 +722,11 @@ PHPAPI void php_output_handler_dtor(php_output_handler *handler)
718722
* Destroy and free an output handler */
719723
PHPAPI void php_output_handler_free(php_output_handler **h)
720724
{
721-
if (*h) {
722-
php_output_handler_dtor(*h);
723-
efree(*h);
725+
php_output_handler *handler = *h;
726+
if (handler) {
724727
*h = NULL;
728+
php_output_handler_dtor(handler);
729+
efree(handler);
725730
}
726731
}
727732
/* }}} */

tests/output/gh20352.phpt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
GH-20352 (UAF in php_output_handler_free via re-entrant ob_start() during error deactivation)
3+
--FILE--
4+
<?php
5+
class Test {
6+
public function __destruct() {
7+
// Spray output stack
8+
for ($i = 0; $i < 1000; $i++)
9+
ob_start(static function() {});
10+
}
11+
12+
public function __invoke($x) {
13+
// Trigger php_output_deactivate() through forbidden operation
14+
ob_start('foo');
15+
return $x;
16+
}
17+
}
18+
19+
ob_start(new Test, 1);
20+
21+
echo "trigger bug";
22+
?>
23+
--EXPECTF--
24+
Fatal error: ob_start(): Cannot use output buffering in output buffering display handlers in %s on line %d

0 commit comments

Comments
 (0)