diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php index 353bd84f3f6f7..fe2246e68b21a 100644 --- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php @@ -97,8 +97,10 @@ public function formatArgs(array $args): string $formattedValue = ''.strtolower(htmlspecialchars(var_export($item[1], true), \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset)).''; } elseif ('resource' === $item[0]) { $formattedValue = 'resource'; + } elseif (preg_match('/[^\x07-\x0D\x1B\x20-\xFF]/', $item[1])) { + $formattedValue = 'binary string'; } else { - $formattedValue = str_replace("\n", '', htmlspecialchars(var_export($item[1], true), \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset)); + $formattedValue = str_replace("\n", '', $this->escape(var_export($item[1], true))); } $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", htmlspecialchars($key, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset), $formattedValue); diff --git a/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php b/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php index 92434b8e94506..08685fa21e867 100644 --- a/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php +++ b/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php @@ -173,6 +173,8 @@ private function formatArgs(array $args): string $formattedValue = ''.strtolower(var_export($item[1], true)).''; } elseif ('resource' === $item[0]) { $formattedValue = 'resource'; + } elseif (preg_match('/[^\x07-\x0D\x1B\x20-\xFF]/', $item[1])) { + $formattedValue = 'binary string'; } else { $formattedValue = str_replace("\n", '', $this->escape(var_export($item[1], true))); } diff --git a/src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php b/src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php index 6680b95a0cc3d..4ab602337159b 100644 --- a/src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php +++ b/src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php @@ -54,4 +54,45 @@ public static function getRenderData(): iterable $expectedNonDebug, ]; } + + public function testRendersStackWithoutBinaryStrings() + { + if (\PHP_VERSION_ID >= 70400) { + // make sure method arguments are available in stack traces (see https://www.php.net/manual/en/ini.core.php) + ini_set('zend.exception_ignore_args', false); + } + + $binaryData = file_get_contents(__DIR__ . '/../Fixtures/pixel.png'); + $exception = $this->getRuntimeException($binaryData); + + $rendered = (new HtmlErrorRenderer(true))->render($exception)->getAsString(); + + $this->assertStringContainsString( + "buildRuntimeException('FooException')", + $rendered, + '->render() contains the method call with "FooException"' + ); + + $this->assertStringContainsString( + 'getRuntimeException(binary string)', + $rendered, + '->render() contains the method call with "binary string" replacement' + ); + + $this->assertStringContainsString( + 'binary string', + $rendered, + '->render() returns the HTML content with "binary string" replacement' + ); + } + + private function getRuntimeException(string $unusedArgument): \RuntimeException + { + return $this->buildRuntimeException('FooException'); + } + + private function buildRuntimeException(string $message): \RuntimeException + { + return new \RuntimeException($message); + } } diff --git a/src/Symfony/Component/ErrorHandler/Tests/Fixtures/pixel.png b/src/Symfony/Component/ErrorHandler/Tests/Fixtures/pixel.png new file mode 100644 index 0000000000000..35269f61fcde4 Binary files /dev/null and b/src/Symfony/Component/ErrorHandler/Tests/Fixtures/pixel.png differ