bug #20127 [HttpFoundation] JSONP callback validation (ro0NL)
This PR was submitted for the master branch but it was merged into the 2.7 branch instead (closes #20127).
Discussion
----------
[HttpFoundation] JSONP callback validation
| Q | A
| ------------- | ---
| Branch? | "master"
| Bug fix? | yes
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #17923
| License | MIT
| Doc PR | reference to the documentation PR, if any
Maybe this is too small for a new dep, but at least it's stable. Symfony itself will make no assumption on validation by default, ie. things should keep working as usual.
Commits
-------
1159f8b
[HttpFoundation] JSONP callback validation
This commit is contained in:
commit
d040748e16
@ -80,11 +80,19 @@ class JsonResponse extends Response
|
|||||||
public function setCallback($callback = null)
|
public function setCallback($callback = null)
|
||||||
{
|
{
|
||||||
if (null !== $callback) {
|
if (null !== $callback) {
|
||||||
// taken from http://www.geekality.net/2011/08/03/valid-javascript-identifier/
|
// partially token from http://www.geekality.net/2011/08/03/valid-javascript-identifier/
|
||||||
$pattern = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*+$/u';
|
// partially token from https://github.com/willdurand/JsonpCallbackValidator
|
||||||
|
// JsonpCallbackValidator is released under the MIT License. See https://github.com/willdurand/JsonpCallbackValidator/blob/v1.1.0/LICENSE for details.
|
||||||
|
// (c) William Durand <william.durand1@gmail.com>
|
||||||
|
$pattern = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*(?:\[(?:"(?:\\\.|[^"\\\])*"|\'(?:\\\.|[^\'\\\])*\'|\d+)\])*?$/u';
|
||||||
|
$reserved = array(
|
||||||
|
'break', 'do', 'instanceof', 'typeof', 'case', 'else', 'new', 'var', 'catch', 'finally', 'return', 'void', 'continue', 'for', 'switch', 'while',
|
||||||
|
'debugger', 'function', 'this', 'with', 'default', 'if', 'throw', 'delete', 'in', 'try', 'class', 'enum', 'extends', 'super', 'const', 'export',
|
||||||
|
'import', 'implements', 'let', 'private', 'public', 'yield', 'interface', 'package', 'protected', 'static', 'null', 'true', 'false',
|
||||||
|
);
|
||||||
$parts = explode('.', $callback);
|
$parts = explode('.', $callback);
|
||||||
foreach ($parts as $part) {
|
foreach ($parts as $part) {
|
||||||
if (!preg_match($pattern, $part)) {
|
if (!preg_match($pattern, $part) || in_array($part, $reserved, true)) {
|
||||||
throw new \InvalidArgumentException('The callback name is not valid.');
|
throw new \InvalidArgumentException('The callback name is not valid.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,6 +213,14 @@ class JsonResponseTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
JsonResponse::create($serializable);
|
JsonResponse::create($serializable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testSetComplexCallback()
|
||||||
|
{
|
||||||
|
$response = JsonResponse::fromJsonString('{foo: "bar"}');
|
||||||
|
$response->setCallback('ಠ_ಠ["foo"].bar[0]');
|
||||||
|
|
||||||
|
$this->assertEquals('/**/ಠ_ಠ["foo"].bar[0]({foo: "bar"});', $response->getContent());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (interface_exists('JsonSerializable')) {
|
if (interface_exists('JsonSerializable')) {
|
||||||
|
Reference in New Issue
Block a user