diff --git a/src/Symfony/Component/Debug/ExceptionHandler.php b/src/Symfony/Component/Debug/ExceptionHandler.php index 2be65ab6fe46..cda0bd22ca7b 100644 --- a/src/Symfony/Component/Debug/ExceptionHandler.php +++ b/src/Symfony/Component/Debug/ExceptionHandler.php @@ -15,7 +15,7 @@ use Symfony\Component\Debug\Exception\OutOfMemoryException; use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; -@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', ExceptionHandler::class, \Symfony\Component\ErrorHandler\ExceptionHandler::class), E_USER_DEPRECATED); +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', ExceptionHandler::class, \Symfony\Component\ErrorHandler\ErrorHandler::class), E_USER_DEPRECATED); /** * ExceptionHandler converts an exception to a Response object. @@ -31,7 +31,7 @@ * * @final since Symfony 4.3 * - * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\ExceptionHandler instead. + * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\ErrorHandler instead. */ class ExceptionHandler { diff --git a/src/Symfony/Component/ErrorHandler/Debug.php b/src/Symfony/Component/ErrorHandler/Debug.php index 392abdb47528..e3bb55c0a074 100644 --- a/src/Symfony/Component/ErrorHandler/Debug.php +++ b/src/Symfony/Component/ErrorHandler/Debug.php @@ -44,7 +44,6 @@ public static function enable($errorReportingLevel = E_ALL, $displayErrors = tru if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { ini_set('display_errors', 0); - ExceptionHandler::register(); } elseif ($displayErrors && (!filter_var(ini_get('log_errors'), FILTER_VALIDATE_BOOLEAN) || ini_get('error_log'))) { // CLI - display errors only if they're not already logged to STDERR ini_set('display_errors', 1); diff --git a/src/Symfony/Component/ErrorHandler/ErrorHandler.php b/src/Symfony/Component/ErrorHandler/ErrorHandler.php index 2a2a8ca384ba..fa54ac90ac58 100644 --- a/src/Symfony/Component/ErrorHandler/ErrorHandler.php +++ b/src/Symfony/Component/ErrorHandler/ErrorHandler.php @@ -21,7 +21,6 @@ use Symfony\Component\ErrorHandler\FatalErrorHandler\FatalErrorHandlerInterface; use Symfony\Component\ErrorHandler\FatalErrorHandler\UndefinedFunctionFatalErrorHandler; use Symfony\Component\ErrorHandler\FatalErrorHandler\UndefinedMethodFatalErrorHandler; -use Symfony\Component\ErrorRenderer\Exception\FlattenException; /** * A generic ErrorHandler for the PHP engine. @@ -414,7 +413,7 @@ public function handleError($type, $message, $file, $line) } if (false !== strpos($message, "class@anonymous\0")) { - $logMessage = $this->levels[$type].': '.(new FlattenException())->setMessage($message)->getMessage(); + $logMessage = $this->parseAnonymousClass($message); } else { $logMessage = $this->levels[$type].': '.$message; } @@ -539,7 +538,7 @@ public function handleException($exception, array $error = null) if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) { if (false !== strpos($message = $exception->getMessage(), "class@anonymous\0")) { - $message = (new FlattenException())->setMessage($message)->getMessage(); + $message = $this->parseAnonymousClass($message); } if ($exception instanceof FatalErrorException) { if ($exception instanceof FatalThrowableError) { @@ -712,4 +711,15 @@ private function cleanTrace($backtrace, $type, $file, $line, $throw) return $lightTrace; } + + /** + * Parse the error message by removing the anonymous class notation + * and using the parent class instead if possible. + */ + private function parseAnonymousClass(string $message): string + { + return preg_replace_callback('/class@anonymous\x00.*?\.php0x?[0-9a-fA-F]++/', static function ($m) { + return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0]; + }, $message); + } } diff --git a/src/Symfony/Component/ErrorHandler/ExceptionHandler.php b/src/Symfony/Component/ErrorHandler/ExceptionHandler.php deleted file mode 100644 index 577234a8d9b5..000000000000 --- a/src/Symfony/Component/ErrorHandler/ExceptionHandler.php +++ /dev/null @@ -1,187 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler; - -use Symfony\Component\ErrorHandler\Exception\OutOfMemoryException; -use Symfony\Component\ErrorRenderer\ErrorRenderer\HtmlErrorRenderer; -use Symfony\Component\ErrorRenderer\Exception\FlattenException; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; - -/** - * ExceptionHandler converts an exception to a Response object. - * - * It is mostly useful in debug mode to replace the default PHP/XDebug - * output with something prettier and more useful. - * - * As this class is mainly used during Kernel boot, where nothing is yet - * available, the Response content is always HTML. - * - * @author Fabien Potencier - * @author Nicolas Grekas - * - * @final since Symfony 4.3 - */ -class ExceptionHandler -{ - private $debug; - private $charset; - private $handler; - private $caughtBuffer; - private $caughtLength; - private $fileLinkFormat; - private $htmlErrorRenderer; - - public function __construct(bool $debug = true, string $charset = null, $fileLinkFormat = null) - { - $this->debug = $debug; - $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8'; - $this->fileLinkFormat = $fileLinkFormat; - } - - /** - * Registers the exception handler. - * - * @param bool $debug Enable/disable debug mode, where the stack trace is displayed - * @param string|null $charset The charset used by exception messages - * @param string|null $fileLinkFormat The IDE link template - * - * @return static - */ - public static function register($debug = true, $charset = null, $fileLinkFormat = null) - { - $handler = new static($debug, $charset, $fileLinkFormat); - - $prev = set_exception_handler([$handler, 'handle']); - if (\is_array($prev) && $prev[0] instanceof ErrorHandler) { - restore_exception_handler(); - $prev[0]->setExceptionHandler([$handler, 'handle']); - } - - return $handler; - } - - /** - * Sets a user exception handler. - * - * @param callable $handler An handler that will be called on Exception - * - * @return callable|null The previous exception handler if any - */ - public function setHandler(callable $handler = null) - { - $old = $this->handler; - $this->handler = $handler; - - return $old; - } - - /** - * Sets the format for links to source files. - * - * @param string|FileLinkFormatter $fileLinkFormat The format for links to source files - * - * @return string The previous file link format - */ - public function setFileLinkFormat($fileLinkFormat) - { - $old = $this->fileLinkFormat; - $this->fileLinkFormat = $fileLinkFormat; - - return $old; - } - - /** - * Sends a response for the given Exception. - * - * To be as fail-safe as possible, the exception is first handled - * by our simple exception handler, then by the user exception handler. - * The latter takes precedence and any output from the former is cancelled, - * if and only if nothing bad happens in this handling path. - */ - public function handle(\Exception $exception) - { - if (null === $this->handler || $exception instanceof OutOfMemoryException) { - $this->sendPhpResponse($exception); - - return; - } - - $caughtLength = $this->caughtLength = 0; - - ob_start(function ($buffer) { - $this->caughtBuffer = $buffer; - - return ''; - }); - - $this->sendPhpResponse($exception); - while (null === $this->caughtBuffer && ob_end_flush()) { - // Empty loop, everything is in the condition - } - if (isset($this->caughtBuffer[0])) { - ob_start(function ($buffer) { - if ($this->caughtLength) { - // use substr_replace() instead of substr() for mbstring overloading resistance - $cleanBuffer = substr_replace($buffer, '', 0, $this->caughtLength); - if (isset($cleanBuffer[0])) { - $buffer = $cleanBuffer; - } - } - - return $buffer; - }); - - echo $this->caughtBuffer; - $caughtLength = ob_get_length(); - } - $this->caughtBuffer = null; - - try { - ($this->handler)($exception); - $this->caughtLength = $caughtLength; - } catch (\Exception $e) { - if (!$caughtLength) { - // All handlers failed. Let PHP handle that now. - throw $exception; - } - } - } - - /** - * Sends the error associated with the given Exception as a plain PHP response. - * - * This method uses plain PHP functions like header() and echo to output - * the response. - * - * @param \Throwable|FlattenException $exception A \Throwable or FlattenException instance - */ - public function sendPhpResponse($exception) - { - if ($exception instanceof \Throwable) { - $exception = FlattenException::createFromThrowable($exception); - } - - if (!headers_sent()) { - header(sprintf('HTTP/1.0 %s', $exception->getStatusCode())); - foreach ($exception->getHeaders() as $name => $value) { - header($name.': '.$value, false); - } - header('Content-Type: text/html; charset='.$this->charset); - } - - if (null === $this->htmlErrorRenderer) { - $this->htmlErrorRenderer = new HtmlErrorRenderer($this->debug, $this->charset, $this->fileLinkFormat); - } - - echo $this->htmlErrorRenderer->render($exception); - } -} diff --git a/src/Symfony/Component/ErrorHandler/Tests/ExceptionHandlerTest.php b/src/Symfony/Component/ErrorHandler/Tests/ExceptionHandlerTest.php deleted file mode 100644 index db01374b9170..000000000000 --- a/src/Symfony/Component/ErrorHandler/Tests/ExceptionHandlerTest.php +++ /dev/null @@ -1,144 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\ErrorHandler\Exception\OutOfMemoryException; -use Symfony\Component\ErrorHandler\ExceptionHandler; -use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; - -require_once __DIR__.'/HeaderMock.php'; - -class ExceptionHandlerTest extends TestCase -{ - protected function setUp() - { - testHeader(); - } - - protected function tearDown() - { - testHeader(); - } - - /** - * @group legacy - */ - public function testDebug() - { - $handler = new ExceptionHandler(false); - - ob_start(); - $handler->sendPhpResponse(new \RuntimeException('Foo')); - $response = ob_get_clean(); - - $this->assertContains('The server returned a "500 Internal Server Error".', $response); - $this->assertNotContains('
', $response); - - $handler = new ExceptionHandler(true); - - ob_start(); - $handler->sendPhpResponse(new \RuntimeException('Foo')); - $response = ob_get_clean(); - - $this->assertContains('

Foo

', $response); - $this->assertContains('
', $response); - - // taken from https://www.owasp.org/index.php/Cross-site_Scripting_(XSS) - $htmlWithXss = ' click me! '; - ob_start(); - $handler->sendPhpResponse(new \RuntimeException($htmlWithXss)); - $response = ob_get_clean(); - - $this->assertContains(sprintf('

%s

', htmlspecialchars($htmlWithXss, ENT_COMPAT | ENT_SUBSTITUTE, 'UTF-8')), $response); - } - - public function testStatusCode() - { - $handler = new ExceptionHandler(false, 'iso8859-1'); - - ob_start(); - $handler->sendPhpResponse(new NotFoundHttpException('Foo')); - $response = ob_get_clean(); - - $this->assertContains('The server returned a "404 Not Found".', $response); - - $expectedHeaders = [ - ['HTTP/1.0 404', true, null], - ['Content-Type: text/html; charset=iso8859-1', true, null], - ]; - - $this->assertSame($expectedHeaders, testHeader()); - } - - public function testHeaders() - { - $handler = new ExceptionHandler(false, 'iso8859-1'); - - ob_start(); - $handler->sendPhpResponse(new MethodNotAllowedHttpException(['POST'])); - $response = ob_get_clean(); - - $expectedHeaders = [ - ['HTTP/1.0 405', true, null], - ['Allow: POST', false, null], - ['Content-Type: text/html; charset=iso8859-1', true, null], - ]; - - $this->assertSame($expectedHeaders, testHeader()); - } - - public function testNestedExceptions() - { - $handler = new ExceptionHandler(true); - ob_start(); - $handler->sendPhpResponse(new \RuntimeException('Foo', 0, new \RuntimeException('Bar'))); - $response = ob_get_clean(); - - $this->assertStringMatchesFormat('%A

Foo

%A

Bar

%A', $response); - } - - public function testHandle() - { - $exception = new \Exception('foo'); - - $handler = $this->getMockBuilder('Symfony\Component\ErrorHandler\ExceptionHandler')->setMethods(['sendPhpResponse'])->getMock(); - $handler - ->expects($this->exactly(2)) - ->method('sendPhpResponse'); - - $handler->handle($exception); - - $handler->setHandler(function ($e) use ($exception) { - $this->assertSame($exception, $e); - }); - - $handler->handle($exception); - } - - public function testHandleOutOfMemoryException() - { - $exception = new OutOfMemoryException('foo', 0, E_ERROR, __FILE__, __LINE__); - - $handler = $this->getMockBuilder('Symfony\Component\ErrorHandler\ExceptionHandler')->setMethods(['sendPhpResponse'])->getMock(); - $handler - ->expects($this->once()) - ->method('sendPhpResponse'); - - $handler->setHandler(function ($e) { - $this->fail('OutOfMemoryException should bypass the handler'); - }); - - $handler->handle($exception); - } -} diff --git a/src/Symfony/Component/ErrorHandler/Tests/MockExceptionHandler.php b/src/Symfony/Component/ErrorHandler/Tests/MockExceptionHandler.php deleted file mode 100644 index 700990de58ec..000000000000 --- a/src/Symfony/Component/ErrorHandler/Tests/MockExceptionHandler.php +++ /dev/null @@ -1,24 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Tests; - -use Symfony\Component\ErrorHandler\ExceptionHandler; - -class MockExceptionHandler extends ExceptionHandler -{ - public $e; - - public function handle(\Exception $e) - { - $this->e = $e; - } -} diff --git a/src/Symfony/Component/ErrorHandler/composer.json b/src/Symfony/Component/ErrorHandler/composer.json index 3794930f35b9..ece07645a548 100644 --- a/src/Symfony/Component/ErrorHandler/composer.json +++ b/src/Symfony/Component/ErrorHandler/composer.json @@ -17,8 +17,7 @@ ], "require": { "php": "^7.1.3", - "psr/log": "~1.0", - "symfony/error-renderer": "^4.4|^5.0" + "psr/log": "~1.0" }, "conflict": { "symfony/http-kernel": "<3.4" diff --git a/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php b/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php index 4f7a54291e52..d9227d888baa 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php @@ -16,7 +16,6 @@ use Symfony\Component\Console\Event\ConsoleEvent; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\ErrorHandler\ErrorHandler; -use Symfony\Component\ErrorHandler\ExceptionHandler; use Symfony\Component\ErrorRenderer\ErrorRenderer; use Symfony\Component\ErrorRenderer\ErrorRenderer\HtmlErrorRenderer; use Symfony\Component\ErrorRenderer\Exception\ErrorRendererNotFoundException; @@ -138,19 +137,7 @@ public function configure(Event $event = null) } if ($this->exceptionHandler) { if ($handler instanceof ErrorHandler) { - $h = $handler->setExceptionHandler('var_dump'); - if (\is_array($h) && $h[0] instanceof ExceptionHandler) { - $handler->setExceptionHandler($h); - $handler = $h[0]; - } else { - $handler->setExceptionHandler($this->exceptionHandler); - } - } - if ($handler instanceof ExceptionHandler) { - $handler->setHandler($this->exceptionHandler); - if (null !== $this->fileLinkFormat) { - $handler->setFileLinkFormat($this->fileLinkFormat); - } + $handler->setExceptionHandler($this->exceptionHandler); } $this->exceptionHandler = null; } diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/DebugHandlersListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/DebugHandlersListenerTest.php index 746756cf01c6..f9c0f6b6b730 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/DebugHandlersListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/DebugHandlersListenerTest.php @@ -20,7 +20,6 @@ use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\ErrorHandler\ErrorHandler; -use Symfony\Component\ErrorHandler\ExceptionHandler; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\KernelEvent; @@ -38,9 +37,7 @@ public function testConfigure() $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); $userHandler = function () {}; $listener = new DebugHandlersListener($userHandler, $logger); - $xHandler = new ExceptionHandler(); $eHandler = new ErrorHandler(); - $eHandler->setExceptionHandler([$xHandler, 'handle']); $exception = null; set_error_handler([$eHandler, 'handleError']); @@ -56,7 +53,7 @@ public function testConfigure() throw $exception; } - $this->assertSame($userHandler, $xHandler->setHandler('var_dump')); + $this->assertSame($userHandler, $eHandler->setExceptionHandler('var_dump')); $loggers = $eHandler->setLoggers([]); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy