Skip to content

Commit 10a51be

Browse files
alehonicolas-grekas
authored andcommitted
[ErrorHandler] Don't format binary strings
Calling var_export on a binary string easily causes memory exhaustion if it's called with even a small image. Fixes symfony#53005
1 parent d7ba8ff commit 10a51be

File tree

4 files changed

+46
-1
lines changed

4 files changed

+46
-1
lines changed

src/Symfony/Bridge/Twig/Extension/CodeExtension.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,10 @@ public function formatArgs(array $args): string
9797
$formattedValue = '<em>'.strtolower(htmlspecialchars(var_export($item[1], true), \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset)).'</em>';
9898
} elseif ('resource' === $item[0]) {
9999
$formattedValue = '<em>resource</em>';
100+
} elseif (preg_match('/[^\x07-\x0D\x1B\x20-\xFF]/', $item[1])) {
101+
$formattedValue = '<em>binary string</em>';
100102
} else {
101-
$formattedValue = str_replace("\n", '', htmlspecialchars(var_export($item[1], true), \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset));
103+
$formattedValue = str_replace("\n", '', $this->escape(var_export($item[1], true)));
102104
}
103105

104106
$result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", htmlspecialchars($key, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset), $formattedValue);

src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ private function formatArgs(array $args): string
173173
$formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
174174
} elseif ('resource' === $item[0]) {
175175
$formattedValue = '<em>resource</em>';
176+
} elseif (preg_match('/[^\x07-\x0D\x1B\x20-\xFF]/', $item[1])) {
177+
$formattedValue = '<em>binary string</em>';
176178
} else {
177179
$formattedValue = str_replace("\n", '', $this->escape(var_export($item[1], true)));
178180
}

src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,45 @@ public static function getRenderData(): iterable
5454
$expectedNonDebug,
5555
];
5656
}
57+
58+
public function testRendersStackWithoutBinaryStrings()
59+
{
60+
if (\PHP_VERSION_ID >= 70400) {
61+
// make sure method arguments are available in stack traces (see https://www.php.net/manual/en/ini.core.php)
62+
ini_set('zend.exception_ignore_args', false);
63+
}
64+
65+
$binaryData = file_get_contents(__DIR__ . '/../Fixtures/pixel.png');
66+
$exception = $this->getRuntimeException($binaryData);
67+
68+
$rendered = (new HtmlErrorRenderer(true))->render($exception)->getAsString();
69+
70+
$this->assertStringContainsString(
71+
"buildRuntimeException('FooException')",
72+
$rendered,
73+
'->render() contains the method call with "FooException"'
74+
);
75+
76+
$this->assertStringContainsString(
77+
'getRuntimeException(binary string)',
78+
$rendered,
79+
'->render() contains the method call with "binary string" replacement'
80+
);
81+
82+
$this->assertStringContainsString(
83+
'<em>binary string</em>',
84+
$rendered,
85+
'->render() returns the HTML content with "binary string" replacement'
86+
);
87+
}
88+
89+
private function getRuntimeException(string $unusedArgument): \RuntimeException
90+
{
91+
return $this->buildRuntimeException('FooException');
92+
}
93+
94+
private function buildRuntimeException(string $message): \RuntimeException
95+
{
96+
return new \RuntimeException($message);
97+
}
5798
}
69 Bytes
Loading

0 commit comments

Comments
 (0)