diff --git a/Extension/CodeExtension.php b/Extension/CodeExtension.php index 96ded292..cdeb69a5 100644 --- a/Extension/CodeExtension.php +++ b/Extension/CodeExtension.php @@ -41,8 +41,8 @@ public function __construct(string|FileLinkFormatter $fileLinkFormat, string $pr public function getFilters(): array { return [ - new TwigFilter('abbr_class', $this->abbrClass(...), ['is_safe' => ['html']]), - new TwigFilter('abbr_method', $this->abbrMethod(...), ['is_safe' => ['html']]), + new TwigFilter('abbr_class', $this->abbrClass(...), ['is_safe' => ['html'], 'pre_escape' => 'html']), + new TwigFilter('abbr_method', $this->abbrMethod(...), ['is_safe' => ['html'], 'pre_escape' => 'html']), new TwigFilter('format_args', $this->formatArgs(...), ['is_safe' => ['html']]), new TwigFilter('format_args_as_text', $this->formatArgsAsText(...)), new TwigFilter('file_excerpt', $this->fileExcerpt(...), ['is_safe' => ['html']]), @@ -84,22 +84,23 @@ public function formatArgs(array $args): string $result = []; foreach ($args as $key => $item) { if ('object' === $item[0]) { + $item[1] = htmlspecialchars($item[1], \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset); $parts = explode('\\', $item[1]); $short = array_pop($parts); $formattedValue = sprintf('object(%s)', $item[1], $short); } elseif ('array' === $item[0]) { - $formattedValue = sprintf('array(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]); + $formattedValue = sprintf('array(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : htmlspecialchars(var_export($item[1], true), \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset)); } elseif ('null' === $item[0]) { $formattedValue = 'null'; } elseif ('boolean' === $item[0]) { - $formattedValue = ''.strtolower(var_export($item[1], true)).''; + $formattedValue = ''.strtolower(htmlspecialchars(var_export($item[1], true), \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset)).''; } elseif ('resource' === $item[0]) { $formattedValue = 'resource'; } else { $formattedValue = str_replace("\n", '', htmlspecialchars(var_export($item[1], true), \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset)); } - $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue); + $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", htmlspecialchars($key, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset), $formattedValue); } return implode(', ', $result); @@ -161,11 +162,14 @@ public function formatFile(string $file, int $line, string $text = null): string $file = trim($file); if (null === $text) { - $text = $file; - if (null !== $rel = $this->getFileRelative($text)) { - $rel = explode('/', $rel, 2); - $text = sprintf('%s%s', $this->projectDir, $rel[0], '/'.($rel[1] ?? '')); + if (null !== $rel = $this->getFileRelative($file)) { + $rel = explode('/', htmlspecialchars($rel, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset), 2); + $text = sprintf('%s%s', htmlspecialchars($this->projectDir, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset), $rel[0], '/'.($rel[1] ?? '')); + } else { + $text = htmlspecialchars($file, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset); } + } else { + $text = htmlspecialchars($text, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset); } if (0 < $line) { diff --git a/Tests/Extension/CodeExtensionTest.php b/Tests/Extension/CodeExtensionTest.php index ae7cf786..08defaac 100644 --- a/Tests/Extension/CodeExtensionTest.php +++ b/Tests/Extension/CodeExtensionTest.php @@ -14,6 +14,8 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\CodeExtension; use Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter; +use Twig\Environment; +use Twig\Loader\ArrayLoader; class CodeExtensionTest extends TestCase { @@ -28,42 +30,136 @@ public function testFileRelative() $this->assertEquals('file.txt', $this->getExtension()->getFileRelative(\DIRECTORY_SEPARATOR.'project'.\DIRECTORY_SEPARATOR.'file.txt')); } - /** - * @dataProvider getClassNameProvider - */ - public function testGettingClassAbbreviation($class, $abbr) + public function testClassAbbreviationIntegration() { - $this->assertEquals($this->getExtension()->abbrClass($class), $abbr); + $data = [ + 'fqcn' => 'F\Q\N\Foo', + 'xss' => '