8000 Merge branch '2.7' into 2.8 · symfony/symfony@899bf99 · GitHub
[go: up one dir, main page]

Skip to content

Commit 899bf99

Browse files
Merge branch '2.7' into 2.8
* 2.7: [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 a920061 + 95c6193 commit 899bf99

File tree

10 files changed

+119
-25
lines changed
  • Security/Http
  • 10 files changed

    +119
    -25
    lines changed

    appveyor.yml

    Lines changed: 1 addition & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -31,6 +31,7 @@ install:
    3131
    - 7z x php_memcache-3.0.8-5.3-nts-vc9-x86.zip -y >nul
    3232
    - cd ..
    3333
    - copy /Y php.ini-development php.ini-min
    34+
    - echo memory_limit=-1 >> php.ini-min
    3435
    - echo serialize_precision=14 >> php.ini-min
    3536
    - echo max_execution_time=1200 >> php.ini-min
    3637
    - 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
    @@ -505,9 +505,21 @@ public function __toString()
    505505
    return trigger_error($e, E_USER_ERROR);
    506506
    }
    507507

    508+
    $cookieHeader = '';
    509+
    $cookies = array();
    510+
    511+
    foreach ($this->cookies as $k => $v) {
    512+
    $cookies[] = $k.'='.$v;
    513+
    }
    514+
    515+
    if (!empty($cookies)) {
    516+
    $cookieHeader = 'Cookie: '.implode('; ', $cookies)."\r\n";
    517+
    }
    518+
    508519
    return
    509520
    sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n".
    510-
    $this->headers."\r\n".
    521+
    $this->headers.
    522+
    $cookieHeader."\r\n".
    511523
    $content;
    512524
    }
    513525

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

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

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

    1458-
    $this->assertContains('Accept-Language: zh, en-us; q=0.8, en; q=0.6', $request->__toString());
    1459+
    $asString = (string) $request;
    1460+
    1461+
    $this->assertContains('Accept-Language: zh, en-us; q=0.8, en; q=0.6', $asString);
    1462+
    $this->assertContains('Cookie: Foo=Bar', $asString);
    1463+
    1464+
    $request->cookies->set('Another', 'Cookie');
    1465+
    1466+
    $asString = (string) $request;
    1467+
    1468+
    $this->assertContains('Cookie: Foo=Bar; Another=Cookie', $asString);
    14591469
    }
    14601470

    14611471
    public function testIsMethod()

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

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

    109109
    if (T_CLASS === $token[0]) {
    110-
    // Skip usage of ::class constant
    111-
    $isClassConstant = false;
    110+
    // Skip usage of ::class constant and anonymous classes
    111+
    $skipClassToken = false;
    112112
    for ($j = $i - 1; $j > 0; --$j) {
    113113
    if (!isset($tokens[$j][1])) {
    114114
    break;
    115115
    }
    116116

    117-
    if (T_DOUBLE_COLON === $tokens[$j][0]) {
    118-
    $isClassConstant = true;
    117+
    if (T_DOUBLE_COLON === $tokens[$j][0] || T_NEW === $tokens[$j][0]) {
    118+
    $skipClassToken = true;
    119119
    break;
    120120
    } elseif (!in_array($tokens[$j][0], array(T_WHITESPACE, T_DOC_COMMENT, T_COMMENT))) {
    121121
    break;
    122122
    }
    123123
    }
    124124

    125-
    if (!$isClassConstant) {
    125+
    if (!$skipClassToken) {
    126126
    $class = true;
    127127
    }
    128128
    }
    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
    @@ -58,6 +58,17 @@ public function testLoadVariadic()
    5858
    $this->loader->load(__DIR__.'/../Fixtures/OtherAnnotatedClasses/VariadicClass.php');
    5959
    }
    6060

    61+
    /**
    62+
    * @requires PHP 7.0
    63+
    */
    64+
    public function testLoadAnonymousClass()
    65+
    {
    66+
    $this->reader->expects($this->never())->method('getClassAnnotation');
    67+
    $this->reader->expects($this->never())->method('getMethodAnnotations');
    68+
    69+
    $this->loader->load(__DIR__.'/../Fixtures/OtherAnnotatedClasses/AnonymousClassInTrait.php');
    70+
    }
    71+
    6172
    public function testSupports()
    6273
    {
    6374
    $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
    @@ -39,8 +39,6 @@ class ContextListener implements ListenerInterface
    3939
    private $dispatcher;
    4040
    private $registered;
    4141

    42-
    private static $unserializeExceptionCode = 0x37313bc;
    43-
    4442
    public function __construct(TokenStorageInterface $tokenStorage, array $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
    4543
    {
    4644
    if (empty($contextKey)) {
    @@ -180,7 +178,7 @@ private function safelyUnserialize($serializedToken)
    180178
    $prevUnserializeHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
    181179
    $prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = array()) use (&$prevErrorHandler) {
    182180
    if (__FILE__ === $file) {
    183-
    throw new \UnexpectedValueException($msg, self::$unserializeExceptionCode);
    181+
    throw new \UnexpectedValueException($msg, 0x37313bc);
    184182
    }
    185183

    186184
    return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false;
    @@ -194,7 +192,7 @@ private function safelyUnserialize($serializedToken)
    194192
    restore_error_handler();
    195193
    ini_set('unserialize_callback_func', $prevUnserializeHandler);
    196194
    if ($e) {
    197-
    if (!$e instanceof \UnexpectedValueException || self::$unserializeExceptionCode !== $e->getCode()) {
    195+
    if (!$e instanceof \UnexpectedValueException || 0x37313bc !== $e->getCode()) {
    198196
    throw $e;
    199197
    }
    200198
    if ($this->logger) {
    @@ -210,6 +208,6 @@ private function safelyUnserialize($serializedToken)
    210208
    */
    211209
    public static function handleUnserializeCallback($class)
    212210
    {
    213-
    throw new \UnexpectedValueException('Class not found: '.$class, self::$unserializeExceptionCode);
    211+
    throw new \UnexpectedValueException('Class not found: '.$class, 0x37313bc);
    214212
    }
    215213
    }

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

    Lines changed: 10 additions & 7 deletions
    Original file line numberDiff line numberDiff line change
    @@ -15,6 +15,7 @@
    1515
    use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter;
    1616
    use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
    1717
    use Symfony\Component\HttpFoundation\Request;
    18+
    use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
    1819
    use Symfony\Component\Security\Core\Exception\InvalidArgumentException;
    1920
    use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
    2021
    use Symfony\Component\Security\Csrf\CsrfToken;
    @@ -118,15 +119,17 @@ protected function attemptAuthentication(Request $request)
    118119
    }
    119120
    }
    120121

    121-
    if ($this->options['post_only']) {
    122-
    $username = trim(ParameterBagUtils::getParameterBagValue($request->request, $this->options['username_parameter']));
    123-
    $password = ParameterBagUtils::getParameterBagValue($request->request, $this->options['password_parameter']);
    124-
    } else {
    125-
    $username = trim(ParameterBagUtils::getRequestParameterValue($request, $this->options['username_parameter']));
    126-
    $password = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']);
    122+
    $requestBag = $this->options['post_only'] ? $request->request : $request;
    123+
    $username = ParameterBagUtils::getParameterBagValue($requestBag, $this->options['username_parameter']);
    124+
    $password = ParameterBagUtils::getParameterBagValue($requestBag, $this->options['password_parameter']);
    125+
    126+
    if (!\is_string($username) || (\is_object($username) && !\method_exists($username, '__toString'))) {
    127+
    throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['username_parameter'], \gettype($username)));
    127128
    }
    128129

    129-
    if (strlen($username) > Security::MAX_USERNAME_LENGTH) {
    130+
    $username = trim($username);
    131+
    132+
    if (\strlen($username) > Security::MAX_USERNAME_LENGTH) {
    130133
    throw new BadCredentialsException('Invalid username.');
    131134
    }
    132135

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

    Lines changed: 9 additions & 6 deletions
    Original file line numberDiff line numberDiff line change
    @@ -15,6 +15,7 @@
    1515
    use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
    1616
    use Symfony\Component\HttpFoundation\Request;
    1717
    use Psr\Log\LoggerInterface;
    18+
    use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
    1819
    use Symfony\Component\Security\Csrf\CsrfToken;
    1920
    use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
    2021
    use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
    @@ -95,14 +96,16 @@ protected function attemptAuthentication(Request $request)
    9596
    }
    9697
    }
    9798

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

    107+
    $username = trim($username);
    108+
    106109
    if (strlen($username) > Security::MAX_USERNAME_LENGTH) {
    107110
    throw new BadCredentialsException('Invalid username.');
    108111
    }

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

    Lines changed: 32 additions & 0 deletions
    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\HttpKernel\Event\GetResponseEvent;
    18+
    use Symfony\Component\HttpKernel\HttpKernelInterface;
    19+
    use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
    20+
    use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler;
    21+
    use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler;
    1722
    use Symfony\Component\Security\Http\Firewall\UsernamePasswordFormAuthenticationListener;
    1823
    use Symfony\Component\Security\Core\SecurityContextInterface;
    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