Description
PHP 8.5 is the first PHP release to include a native backtrace with fatal errors. PHP documents this in the PHP 8.5 release notes.
When CakePHP handles a fatal error during shutdown, ExceptionTrap::handleShutdown() reads error_get_last() but only passes its message, file, and line to handleFatalError(). The new trace element is discarded. The resulting FatalErrorException therefore only shows CakePHP's shutdown handler, [internal], and [main], rather than the application call stack that caused the fatal error.
This makes out-of-memory errors especially difficult to diagnose.
On PHP 8.2–8.4, error_get_last() does not provide a trace element, so the existing behaviour should remain unchanged.
Steps to reproduce
-
Run an application on PHP 8.5 with a low memory limit, such as memory_limit=16M.
-
Add a call path that exhausts memory:
final class ReportService
{
public function generate(): void
{
$this->exhaustMemory();
}
private function exhaustMemory(): void
{
$chunks = [];
while (true) {
$chunks[] = str_repeat('x', 1024 * 1024);
}
}
}
-
Request the controller action that calls ReportService::generate().
Actual behaviour
CakePHP reports the memory error, but the stack trace is limited to the shutdown handler:
Cake\Error\FatalErrorException: Allowed memory size exhausted
Stack Trace:
- CORE/src/Error/ExceptionTrap.php:...
- [internal]:??
- [main]:
Expected behaviour
On PHP 8.5+, CakePHP should preserve and format the fatal-error backtrace supplied by error_get_last(), so the reported exception identifies the application call path (for example, ReportService::generate() and the calling controller action).
Trace arguments should remain omitted to avoid exposing sensitive values.
Possible implementation
Use the trace entry from error_get_last() when it is present, and append a formatted version to the fatal error description before passing it to handleFatalError(). The trace is absent on supported PHP 8.2–8.4 versions, so this can be conditional without changing their output.
CakePHP Version
5.4.1
PHP Version
8.5.4
Description
PHP 8.5 is the first PHP release to include a native backtrace with fatal errors. PHP documents this in the PHP 8.5 release notes.
When CakePHP handles a fatal error during shutdown,
ExceptionTrap::handleShutdown()readserror_get_last()but only passes its message, file, and line tohandleFatalError(). The newtraceelement is discarded. The resultingFatalErrorExceptiontherefore only shows CakePHP's shutdown handler,[internal], and[main], rather than the application call stack that caused the fatal error.This makes out-of-memory errors especially difficult to diagnose.
On PHP 8.2–8.4,
error_get_last()does not provide atraceelement, so the existing behaviour should remain unchanged.Steps to reproduce
Run an application on PHP 8.5 with a low memory limit, such as
memory_limit=16M.Add a call path that exhausts memory:
Request the controller action that calls
ReportService::generate().Actual behaviour
CakePHP reports the memory error, but the stack trace is limited to the shutdown handler:
Expected behaviour
On PHP 8.5+, CakePHP should preserve and format the fatal-error backtrace supplied by
error_get_last(), so the reported exception identifies the application call path (for example,ReportService::generate()and the calling controller action).Trace arguments should remain omitted to avoid exposing sensitive values.
Possible implementation
Use the
traceentry fromerror_get_last()when it is present, and append a formatted version to the fatal error description before passing it tohandleFatalError(). The trace is absent on supported PHP 8.2–8.4 versions, so this can be conditional without changing their output.CakePHP Version
5.4.1
PHP Version
8.5.4