8000 Merge branch '2.8' into 3.3 · symfony/symfony@2f8e1b8 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 2f8e1b8

Browse files
Merge branch '2.8' into 3.3
* 2.8: [appveyor] set memory_limit=-1 [Router] Skip anonymous classes when loading annotated routes Fixed Request::__toString ignoring cookies [Security] Fix fatal error on non string username
2 parents 663f3f0 + 899bf99 commit 2f8e1b8

File tree

10 files changed

+120
-26
lines changed

10 files changed

+120
-26
lines changed

appveyor.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ install:
2727
- 7z x php_memcache-3.0.8-5.5-nts-vc11-x86.zip -y >nul
2828
- cd ..
2929
- copy /Y php.ini-development php.ini-min
30+
- echo memory_limit=-1 >> php.ini-min
3031
- echo serialize_precision=14 >> php.ini-min
3132
- echo max_execution_time=1200 >> php.ini-min
3233
- echo date.timezone="America/Los_Angeles" >> php.ini-min

src/Symfony/Component/HttpFoundation/Request.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,9 +531,21 @@ public function __toString()
531531
return trigger_error($e, E_USER_ERROR);
532532
}
533533

534+
$cookieHeader = '';
535+
$cookies = array();
536+
537+
foreach ($this->cookies as $k => $v) {
538+
$cookies[] = $k.'='.$v;
539+
}
540+
541+
if (!empty($cookies)) {
542+
$cookieHeader = 'Cookie: '.implode('; ', $cookies)."\r\n";
543+
}
544+
534545
return
535546
sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n".
536-
$this->headers."\r\n".
547+
$this->headers.
548+
$cookieHeader."\r\n".
537549
$content;
538550
}
539551

src/Symfony/Component/HttpFoundation/Tests/RequestTest.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1523,8 +1523,18 @@ public function testToString()
15231523
$request = new Request();
15241524

15251525
$request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
1526+
$request->cookies->set('Foo', 'Bar');
15261527

1527-
$this->assertContains('Accept-Language: zh, en-us; q=0.8, en; q=0.6', $request->__toString());
1528+
$asString = (string) $request;
1529+
1530+
$this->assertContains('Accept-Language: zh, en-us; q=0.8, en; q=0.6', $asString);
1531+
$this->assertContains('Cookie: Foo=Bar', $asString);
1532+
1533+
$request->cookies->set('Another', 'Cookie');
1534+
1535+
$asString = (string) $request;
1536+
1537+
$this->assertContains('Cookie: Foo=Bar; Another=Cookie', $asString);
15281538
}
15291539

15301540
public function testIsMethod()

src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,22 +112,22 @@ protected function findClass($file)
112112
}
113113

114114
if (T_CLASS === $token[0]) {
115-
// Skip usage of ::class constant
116-
$isClassConstant = false;
115+
// Skip usage of ::class constant and anonymous classes
116+
$skipClassToken = false;
117117
for ($j = $i - 1; $j > 0; --$j) {
118118
if (!isset($tokens[$j][1])) {
119119
break;
120120
}
121121

122-
if (T_DOUBLE_COLON === $tokens[$j][0]) {
123-
$isClassConstant = true;
122+
if (T_DOUBLE_COLON === $tokens[$j][0] || T_NEW === $tokens[$j][0]) {
123+
$skipClassToken = true;
124124
break;
125125
} elseif (!in_array($tokens[$j][0], array(T_WHITESPACE, T_DOC_COMMENT, T_COMMENT))) {
126126
break;
127127
}
128128
}
129129

130-
if (!$isClassConstant) {
130+
if (!$skipClassToken) {
131131
$class = true;
132132
}
133133
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Routing\Tests\Fixtures\OtherAnnotatedClasses;
13+
14+
trait AnonymousClassInTrait
15+
{
16+
public function test()
17+
{
18+
return new class() {
19+
public function foo()
20+
{
21+
}
22+
};
23+
}
24+
}

src/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,17 @@ public function testLoadVariadic()
6767
$this->loader->load(__DIR__.'/../Fixtures/OtherAnnotatedClasses/VariadicClass.php');
6868
}
6969

70+
/**
71+
* @requires PHP 7.0
72+
*/
73+
public function testLoadAnonymousClass()
74+
{
75+
$this->reader->expects($this->never())->method('getClassAnnotation');
76+
$this->reader->expects($this->never())->method('getMethodAnnotations');
77+
78+
$this->loader->load(__DIR__.'/../Fixtures/OtherAnnotatedClasses/AnonymousClassInTrait.php');
79+
}
80+
7081
public function testSupports()
7182
{
7283
$fixture = __DIR__.'/../Fixtures/annotated.php';

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

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

46-
private static $unserializeExceptionCode = 0x37313bc;
47-
4846
public function __construct(TokenStorageInterface $tokenStorage, array $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, AuthenticationTrustResolverInterface $trustResolver = null)
4947
{
5048
if (empty($contextKey)) {
@@ -185,7 +183,7 @@ private function safelyUnserialize($serializedToken)
185183
$prevUnserializeHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
186184
$prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = array()) use (&$prevErrorHandler) {
187185
if (__FILE__ === $file) {
188-
throw new \UnexpectedValueException($msg, self::$unserializeExceptionCode);
186+
throw new \UnexpectedValueException($msg, 0x37313bc);
189187
}
190188

191189
return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false;
@@ -199,7 +197,7 @@ private function safelyUnserialize($serializedToken)
199197
restore_error_handler();
200198
ini_set('unserialize_callback_func', $prevUnserializeHandler);
201199
if ($e) {
202-
if (!$e instanceof \UnexpectedValueException || self::$unserializeExceptionCode !== $e->getCode()) {
200+
if (!$e instanceof \UnexpectedValueException || 0x37313bc !== $e->getCode()) {
203201
throw $e;
204202
}
205203
if ($this->logger) {
@@ -215,6 +213,6 @@ private function safelyUnserialize($serializedToken)
215213
*/
216214
public static function handleUnserializeCallback($class)
217215
{
218-
throw new \UnexpectedValueException('Class not found: '.$class, self::$unserializeExceptionCode);
216+
throw new \UnexpectedValueException('Class not found: '.$class, 0x37313bc);
219217
}
220218
}

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

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
1515
use Symfony\Component\HttpFoundation\Request;
16+
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
1617
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
1718
use Symfony\Component\Security\Csrf\CsrfToken;
1819
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
@@ -98,15 +99,17 @@ protected function attemptAuthentication(Request $request)
9899
}
99100
}
100101

101-
if ($this->options['post_only']) {
102-
$username = trim(ParameterBagUtils::getParameterBagValue($request->request, $this->options['username_parameter']));
103-
$password = ParameterBagUtils::getParameterBagValue($request->request, $this->options['password_parameter']);
104-
} else {
105-
$username = trim(ParameterBagUtils::getRequestParameterValue($request, $this->options['username_parameter']));
106-
$password = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']);
102+
$requestBag = $this->options['post_only'] ? $request->request : $request;
103+
$username = ParameterBagUtils::getParameterBagValue($requestBag, $this->options['username_parameter']);
104+
$password = ParameterBagUtils::getParameterBagValue($requestBag, $this->options['password_parameter']);
105+
106+
if (!\is_string($username) || (\is_object($username) && !\method_exists($username, '__toString'))) {
107+
throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['username_parameter'], \gettype($username)));
107108
}
108109

109-
if (strlen($username) > Security::MAX_USERNAME_LENGTH) {
110+
$username = trim($username);
111+
112+
if (\strlen($username) > Security::MAX_USERNAME_LENGTH) {
110113
throw new BadCredentialsException('Invalid username.');
111114
}
112115

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\HttpFoundation\Request;
1515
use Psr\Log\LoggerInterface;
16+
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
1617
use Symfony\Component\Security\Csrf\CsrfToken;
1718
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
1819
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
@@ -76,14 +77,16 @@ protected function attemptAuthentication(Request $request)
7677
}
7778
}
7879

79-
if ($this->options['post_only']) {
80-
$username = trim(ParameterBagUtils::getParameterBagValue($request->request, $this->options['username_parameter']));
81-
$password = ParameterBagUtils::getParameterBagValue($request->request, $this->options['password_parameter']);
82-
} else {
83-
$username = trim(ParameterBagUtils::getRequestParameterValue($request, $this->options['username_parameter']));
84-
$password = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']);
80+
$requestBag = $this->options['post_only'] ? $request->request : $request;
81+
$username = ParameterBagUtils::getParameterBagValue($requestBag, $this->options['username_parameter']);
82+
$password = ParameterBagUtils::getParameterBagValue($requestBag, $this->options['password_parameter']);
83+
84+
if (!\is_string($username) || (\is_object($username) && !\method_exists($username, '__toString'))) {
85+
throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['username_parameter'], \gettype($username)));
8586
}
8687

88+
$username = trim($username);
89+
8790
if (strlen($username) > Security::MAX_USERNAME_LENGTH) {
8891
throw new BadCredentialsException('Invalid username.');
8992
}

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

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,15 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\HttpFoundation\Request;
1616
use Symfony\Component\HttpFoundation\Response;
17-
use Symfony\Component\Security\Http\Firewall\UsernamePasswordFormAuthenticationListener;
17+
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
18+
use Symfony\Component\HttpKernel\HttpKernelInterface;
19+
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
1820
use Symfony\Component\Security\Core\Security;
21+
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler;
22+
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler;
23+
use Symfony\Component\Security\Http\Firewall\UsernamePasswordFormAuthenticationListener;
24+
use Symfony\Component\Security\Http\HttpUtils;
25+
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy;
1926

2027
class UsernamePasswordFormAuthenticationListenerTest extends TestCase
2128
{
@@ -69,6 +76,31 @@ public function testHandleWhenUsernameLength($username, $ok)
6976
$listener->handle($event);
7077
}
7178

79+
/**
80+
* @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
81+
* @expectedExceptionMessage The key "_username" must be a string, "array" given.
82+
*/
83+
public function testHandleNonStringUsername()
84+
{
85+
$request = Request::create('/login_check', 'POST', array('_username' => array()));
86+
$request->setSession($this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')->getMock());
87+
88+
$listener = new UsernamePasswordFormAuthenticationListener(
89+
new TokenStorage(),
90+
$this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')->getMock(),
91+
new SessionAuthenticationStrategy(SessionAuthenticationStrategy::NONE),
92+
$httpUtils = new HttpUtils(),
93+
'foo',
94+
new DefaultAuthenticationSuccessHandler($httpUtils),
95+
new DefaultAuthenticationFailureHandler($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $httpUtils),
96+
array('require_previous_session' => false)
97+
);
98+
99+
$event = new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST);
100+
101+
$listener->handle($event);
102+
}
103+
72104
public function getUsernameForLength()
73105
{
74106
return array(

0 commit comments

Comments
 (0)
0