Skip to content

Fixed pathinfo calculation for requests starting with a question mark. #21968

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/Symfony/Component/HttpFoundation/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -1774,6 +1774,9 @@ protected function prepareBaseUrl()

// Does the baseUrl have anything in common with the request_uri?
$requestUri = $this->getRequestUri();
if ($requestUri !== '' && $requestUri[0] !== '/') {
$requestUri = '/'.$requestUri;
}

if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) {
// full $baseUrl matches
Expand Down Expand Up @@ -1846,9 +1849,12 @@ protected function preparePathInfo()
}

// Remove the query string from REQUEST_URI
if ($pos = strpos($requestUri, '?')) {
if (false !== $pos = strpos($requestUri, '?')) {
$requestUri = substr($requestUri, 0, $pos);
}
if ($requestUri !== '' && $requestUri[0] !== '/') {
$requestUri = '/'.$requestUri;
}

$pathInfo = substr($requestUri, strlen($baseUrl));
if (null !== $baseUrl && (false === $pathInfo || '' === $pathInfo)) {
Expand Down
61 changes: 61 additions & 0 deletions src/Symfony/Component/HttpFoundation/Tests/RequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1264,6 +1264,12 @@ public function testGetPathInfo()
$request->initialize(array(), array(), array(), array(), array(), $server);

$this->assertEquals('/path%20test/info', $request->getPathInfo());

$server = array();
$server['REQUEST_URI'] = '?a=b';
$request->initialize(array(), array(), array(), array(), array(), $server);

$this->assertEquals('/', $request->getPathInfo());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please create a new test method for this case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And also tests the query string to be extracted correctly.

}

public function testGetPreferredLanguage()
Expand Down Expand Up @@ -1992,6 +1998,61 @@ public function methodCacheableProvider()
array('CONNECT', false),
);
}

public function nonstandardRequestsData()
{
return array(
array('', '', '/', 'http://host:8080/', ''),
array('/', '', '/', 'http://host:8080/', ''),

array('hello/app.php/x', '', '/x', 'http://host:8080/hello/app.php/x', '/hello', '/hello/app.php'),
array('/hello/app.php/x', '', '/x', 'http://host:8080/hello/app.php/x', '/hello', '/hello/app.php'),

array('', 'a=b', '/', 'http://host:8080/?a=b'),
array('?a=b', 'a=b', '/', 'http://host:8080/?a=b'),
array('/?a=b', 'a=b', '/', 'http://host:8080/?a=b'),

array('x', 'a=b', '/x', 'http://host:8080/x?a=b'),
array('x?a=b', 'a=b', '/x', 'http://host:8080/x?a=b'),
array('/x?a=b', 'a=b', '/x', 'http://host:8080/x?a=b'),

array('hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'),
array('/hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'),

array('hello/app.php/x', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'),
array('hello/app.php/x?a=b', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'),
array('/hello/app.php/x?a=b', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'),
);
}

/**
* @dataProvider nonstandardRequestsData
*/
public function testNonstandardRequests($requestUri, $queryString, $expectedPathInfo, $expectedUri, $expectedBasePath = '', $expectedBaseUrl = null)
{
if (null === $expectedBaseUrl) {
$expectedBaseUrl = $expectedBasePath;
}

$server = array(
'HTTP_HOST' => 'host:8080',
'SERVER_PORT' => '8080',
'QUERY_STRING' => $queryString,
'PHP_SELF' => '/hello/app.php',
'SCRIPT_FILENAME' => '/some/path/app.php',
'REQUEST_URI' => $requestUri,
);

$request = new Request(array(), array(), array(), array(), array(), $server);

$this->assertEquals($expectedPathInfo, $request->getPathInfo());
$this->assertEquals($expectedUri, $request->getUri());
$this->assertEquals($queryString, $request->getQueryString());
$this->assertEquals(8080, $request->getPort());
$this->assertEquals('host:8080', $request->getHttpHost());
$this->assertEquals($expectedBaseUrl, $request->getBaseUrl());
$this->assertEquals($expectedBasePath, $request->getBasePath());
}
}

class RequestContentProxy extends Request
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public function testCheckRequestPath()
// Plus must not decoded to space
$this->assertTrue($utils->checkRequestPath($this->getRequest('/foo+bar'), '/foo+bar'));
// Checking unicode
$this->assertTrue($utils->checkRequestPath($this->getRequest(urlencode('/вход')), '/вход'));
$this->assertTrue($utils->checkRequestPath($this->getRequest('/'.urlencode('вход')), '/вход'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't be changing the existing tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this test only meant to check unicode and not an encoded slash. Should I just leave it failing?

Also it's an interesting situation here: urlencoded slash could be allowed in requests. Then it is not a path separator but part of path segment.
But HttpUtils::checkRequestPath implementation cannot distinguish between /x/ and /x%2F.

}

public function testCheckRequestPathWithUrlMatcherAndResourceNotFound()
Expand Down