Skip to content

Commit fc9236d

Browse files
committed
Merge branch '2.8' into 3.3
* 2.8: [Serializer] Fixed throwing exception with option JSON_PARTIAL_OUTPUT_ON_ERROR Tweaked some styles in the profiler tables [Security] Fail gracefully if the security token cannot be unserialized from the session [Form] AbstractLayoutTest - fix DOMDocument casing bumped Symfony version to 2.8.34 updated VERSION for 2.8.33 updated CHANGELOG for 2.8.33 bumped Symfony version to 2.7.41 updated VERSION for 2.7.40 update CONTRIBUTORS for 2.7.40 updated CHANGELOG for 2.7.40
2 parents 7085569 + eca17ec commit fc9236d

File tree

10 files changed

+148
-38
lines changed

10 files changed

+148
-38
lines changed

CONTRIBUTORS.md

Lines changed: 59 additions & 26 deletions
Large diffs are not rendered by default.

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/events.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
{% endif %}
7575

7676
<tr>
77-
<td class="text-right">{{ listener.priority|default('-') }}</td>
77+
<td class="text-right nowrap">{{ listener.priority|default('-') }}</td>
7878
<td class="font-normal">{{ profiler_dump(listener.stub) }}</td>
7979
</tr>
8080

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,9 @@
168168
<tbody>
169169
{% for message in messages %}
170170
<tr>
171-
<td class="font-normal text-small">{{ message.locale }}</td>
171+
<td class="font-normal text-small nowrap">{{ message.locale }}</td>
172172
<td class="font-normal text-small text-bold nowrap">{{ message.domain }}</td>
173-
<td class="font-normal text-small">{{ message.count }}</td>
173+
<td class="font-normal text-small nowrap">{{ message.count }}</td>
174174
<td>
175175
<span class="nowrap">{{ message.id }}</span>
176176

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,6 @@ table tbody td {
178178
border-width: 1px 0;
179179
}
180180

181-
table tbody td {
182-
{{ mixins.break_long_words|raw }}
183-
}
184-
185181
table tbody div {
186182
margin: .25em 0;
187183
}

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Router/panel.html.twig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@
5555
{% for trace in traces %}
5656
<tr class="{{ trace.level == 1 ? 'status-warning' : trace.level == 2 ? 'status-success' }}">
5757
<td class="font-normal text-muted nowrap">{{ loop.index }}</td>
58-
<td>{{ trace.name }}</td>
59-
<td>{{ trace.path }}</td>
58+
<td class="break-long-words">{{ trace.name }}</td>
59+
<td class="break-long-words">{{ trace.path }}</td>
6060
<td class="font-normal">
6161
{% if trace.level == 1 %}
6262
Path almost matches, but

src/Symfony/Component/Form/Tests/AbstractLayoutTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ protected function assertXpathNodeValue(\DOMElement $element, $expression, $node
5858

5959
protected function assertMatchesXpath($html, $expression, $count = 1)
6060
{
61-
$dom = new \DomDocument('UTF-8');
61+
$dom = new \DOMDocument('UTF-8');
6262
try {
6363
// Wrap in <root> node so we can load HTML with multiple tags at
6464
// the top level

src/Symfony/Component/Security/Http/Firewall/ContextListener.php

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ class ContextListener implements ListenerInterface
4343
private $registered;
4444
private $trustResolver;
4545

46+
private static $unserializeExceptionCode = 0x37313bc;
47+
4648
public function __construct(TokenStorageInterface $tokenStorage, array $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, AuthenticationTrustResolverInterface $trustResolver = null)
4749
{
4850
if (empty($contextKey)) {
@@ -82,7 +84,7 @@ public function handle(GetResponseEvent $event)
8284
return;
8385
}
8486

85-
$token = unserialize($token);
87+
$token = $this->safelyUnserialize($token);
8688

8789
if (null !== $this->logger) {
8890
$this->logger->debug('Read existing security token from the session.', array('key' => $this->sessionKey));
@@ -176,4 +178,43 @@ protected function refreshUser(TokenInterface $token)
176178

177179
throw new \RuntimeException(sprintf('There is no user provider for user "%s".', get_class($user)));
178180
}
181+
182+
private function safelyUnserialize($serializedToken)
183+
{
184+
$e = $token = null;
185+
$prevUnserializeHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
186+
$prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = array()) use (&$prevErrorHandler) {
187+
if (__FILE__ === $file) {
188+
throw new \UnexpectedValueException($msg, self::$unserializeExceptionCode);
189+
}
190+
191+
return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false;
192+
});
193+
194+
try {
195+
$token = unserialize($serializedToken);
196+
} catch (\Error $e) {
197+
} catch (\Exception $e) {
198+
}
199+
restore_error_handler();
200+
ini_set('unserialize_callback_func', $prevUnserializeHandler);
201+
if ($e) {
202+
if (!$e instanceof \UnexpectedValueException || self::$unserializeExceptionCode !== $e->getCode()) {
203+
throw $e;
204+
}
205+
if ($this->logger) {
206+
$this->logger->warning('Failed to unserialize the security token from the session.', array('key' => $this->sessionKey, 'received' => $serializedToken, 'exception' => $e));
207+
}
208+
}
209+
210+
return $token;
211+
}
212+
213+
/**
214+
* @internal
215+
*/
216+
public static function handleUnserializeCallback($class)
217+
{
218+
throw new \UnexpectedValueException('Class not found: '.$class, self::$unserializeExceptionCode);
219+
}
179220
}

src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ public function testInvalidTokenInSession($token)
177177
public function provideInvalidToken()
178178
{
179179
return array(
180+
array('foo'),
181+
array('O:8:"NotFound":0:{}'),
180182
array(serialize(new \__PHP_Incomplete_Class())),
181183
array(serialize(null)),
182184
array(null),

src/Symfony/Component/Serializer/Encoder/JsonEncode.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public function encode($data, $format, array $context = array())
3838

3939
$encodedJson = json_encode($data, $context['json_encode_options']);
4040

41-
if (JSON_ERROR_NONE !== json_last_error()) {
41+
if (JSON_ERROR_NONE !== json_last_error() && (false === $encodedJson || !($context['json_encode_options'] & JSON_PARTIAL_OUTPUT_ON_ERROR))) {
4242
throw new UnexpectedValueException(json_last_error_msg());
4343
}
4444

src/Symfony/Component/Serializer/Tests/Encoder/JsonEncoderTest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,44 @@ public function testOptions()
6565
$this->assertEquals($expected, $this->serializer->serialize($arr, 'json'), 'Context should not be persistent');
6666
}
6767

68+
/**
69+
* @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException
70+
*/
71+
public function testEncodeNotUtf8WithoutPartialOnError()
72+
{
73+
$arr = array(
74+
'utf8' => 'Hello World!',
75+
'notUtf8' => "\xb0\xd0\xb5\xd0",
76+
);
77+
78+
$this->encoder->encode($arr, 'json');
79+
}
80+
81+
public function testEncodeNotUtf8WithPartialOnError()
82+
{
83+
$context = array('json_encode_options' => JSON_PARTIAL_OUTPUT_ON_ERROR);
84+
85+
$arr = array(
86+
'utf8' => 'Hello World!',
87+
'notUtf8' => "\xb0\xd0\xb5\xd0",
88+
);
89+
90+
$result = $this->encoder->encode($arr, 'json', $context);
91+
$jsonLastError = json_last_error();
92+
93+
$this->assertSame(JSON_ERROR_UTF8, $jsonLastError);
94+
$this->assertEquals('{"utf8":"Hello World!","notUtf8":null}', $result);
95+
96+
$this->assertEquals('0', $this->serializer->serialize(NAN, 'json', $context));
97+
}
98+
99+
public function testDecodeFalseString()
100+
{
101+
$result = $this->encoder->decode('false', 'json');
102+
$this->assertSame(JSON_ERROR_NONE, json_last_error());
103+
$this->assertFalse($result);
104+
}
105+
68106
protected function getJsonSource()
69107
{
70108
return '{"foo":"foo","bar":["a","b"],"baz":{"key":"val","key2":"val","A B":"bar","item":[{"title":"title1"},{"title":"title2"}],"Barry":{"FooBar":{"Baz":"Ed","@id":1}}},"qux":"1"}';

0 commit comments

Comments
 (0)