Skip to content
This repository was archived by the owner on May 31, 2024. It is now read-only.

Commit 9e15cb9

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 9853134 + 8c9285e commit 9e15cb9

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

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
}

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),

0 commit comments

Comments
 (0)