diff --git a/src/Symfony/Component/HttpFoundation/JsonResponse.php b/src/Symfony/Component/HttpFoundation/JsonResponse.php index 4672cdc8de..f370867aed 100644 --- a/src/Symfony/Component/HttpFoundation/JsonResponse.php +++ b/src/Symfony/Component/HttpFoundation/JsonResponse.php @@ -80,11 +80,19 @@ class JsonResponse extends Response public function setCallback($callback = null) { if (null !== $callback) { - // taken 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 http://www.geekality.net/2011/08/03/valid-javascript-identifier/ + // 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 + $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); 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.'); } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php index 60d27e4d59..0a0732f473 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php @@ -213,6 +213,14 @@ class JsonResponseTest extends \PHPUnit_Framework_TestCase 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')) {