bug #40807 RequestMatcher issue when _controller is a closure (Plopix)

This PR was merged into the 4.4 branch.

Discussion
----------

RequestMatcher issue when `_controller` is a closure

| Q             | A
| ------------- | ---
| Branch?       |  4.4
| Bug fix?      |  yes
| New feature?  | no
| Deprecations? |  no
| License       | MIT

## Description

If the `matches` method of `RequestMatcher` is used on an attribute which is a closure it crashes.

##  How did we get it

On a project that is using FOS HTTP Cache, we have this configuration

```yaml
fos_http_cache:
    cache_control:
        rules:
     -
                match:
                    attributes: { _controller: ^App\\Controller\\.*::.* }
                headers:
                    overwrite: true
                    cache_control: { public: true, private: false, must_revalidate: true, s_maxage: 3600 }
```

Everything works fine unless you are reaching a controller that is a closure.
You get a
```TypeError: preg_match(): Argument #2 ($subject) must be of type string, Closure given``` which is to me logical.

## Proposed solution

Just testing the type of attribute value and return false before crashing `preg_match`

This PR adds a quick unit test to enforce this.

Commits
-------

66491238e3 Fix issue with RequestMatcher when attribute is a closure
This commit is contained in:
Nyholm 2021-04-15 21:04:28 +02:00
commit d5e8d6ed88
No known key found for this signature in database
GPG Key ID: D6332DE2B6F8FA38
2 changed files with 18 additions and 1 deletions

View File

@ -167,7 +167,11 @@ class RequestMatcher implements RequestMatcherInterface
}
foreach ($this->attributes as $key => $pattern) {
if (!preg_match('{'.$pattern.'}', $request->attributes->get($key))) {
$requestAttribute = $request->attributes->get($key);
if (!\is_string($requestAttribute)) {
return false;
}
if (!preg_match('{'.$pattern.'}', $requestAttribute)) {
return false;
}
}

View File

@ -163,4 +163,17 @@ class RequestMatcherTest extends TestCase
$matcher->matchAttribute('foo', 'babar');
$this->assertFalse($matcher->matches($request));
}
public function testAttributesWithClosure()
{
$matcher = new RequestMatcher();
$request = Request::create('/admin/foo');
$request->attributes->set('_controller', function () {
return new Response('foo');
});
$matcher->matchAttribute('_controller', 'babar');
$this->assertFalse($matcher->matches($request));
}
}