diff --git a/src/Node/Expression/Binary/ObjectDestructuringSetBinary.php b/src/Node/Expression/Binary/ObjectDestructuringSetBinary.php index b47c50fe8..8c5df6a80 100644 --- a/src/Node/Expression/Binary/ObjectDestructuringSetBinary.php +++ b/src/Node/Expression/Binary/ObjectDestructuringSetBinary.php @@ -13,6 +13,7 @@ namespace Twig\Node\Expression\Binary; use Twig\Compiler; use Twig\Error\SyntaxError; +use Twig\Extension\SandboxExtension; use Twig\Node\Expression\AbstractExpression; use Twig\Node\Expression\ArrayExpression; use Twig\Node\Expression\Variable\ContextVariable; @@ -64,7 +65,7 @@ class ObjectDestructuringSetBinary extends AbstractBinary if ($i) { $compiler->raw(', '); } - $compiler->raw('CoreExtension::getAttribute($this->env, $this->source, ')->subcompile($this->getNode('right'))->raw(', ')->repr($mapping['property'])->raw(', [], \\Twig\\Template::ANY_CALL, false, false, false, ')->repr($this->getNode('right')->getTemplateLine())->raw(')'); + $compiler->raw('CoreExtension::getAttribute($this->env, $this->source, ')->subcompile($this->getNode('right'))->raw(', ')->repr($mapping['property'])->raw(', [], \\Twig\\Template::ANY_CALL, false, false, ')->repr($compiler->getEnvironment()->hasExtension(SandboxExtension::class))->raw(', ')->repr($this->getNode('right')->getTemplateLine())->raw(')'); } $compiler->raw(']'); } diff --git a/tests/Extension/SandboxTest.php b/tests/Extension/SandboxTest.php index 151c90d26..c6fd95c83 100644 --- a/tests/Extension/SandboxTest.php +++ b/tests/Extension/SandboxTest.php @@ -423,6 +423,40 @@ class SandboxTest extends TestCase $this->assertEquals('bar', $twig->load('1_basic4')->render(self::$params), 'Sandbox allow some properties'); } + public function testSandboxAllowDestructuring() + { + $template = '{% do {bar: x, foo: y} = obj %}{{ x }}-{{ y }}'; + $twig = $this->getEnvironment(true, [], ['index' => $template], ['do'], [], ['Twig\Tests\Extension\FooObject' => 'foo'], ['Twig\Tests\Extension\FooObject' => 'bar']); + FooObject::reset(); + $this->assertSame('bar-foo', $twig->load('index')->render(self::$params), 'Sandbox allows destructuring when properties and methods are allowed'); + } + + public function testSandboxUnallowedDestructuringProperty() + { + $template = '{% do {bar: x} = obj %}{{ x }}'; + $twig = $this->getEnvironment(true, [], ['index' => $template], ['do']); + try { + $twig->load('index')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception if an unallowed property is read via destructuring'); + } catch (SecurityNotAllowedPropertyError $e) { + $this->assertSame('Twig\Tests\Extension\FooObject', $e->getClassName()); + $this->assertSame('bar', $e->getPropertyName()); + } + } + + public function testSandboxUnallowedDestructuringMethod() + { + $template = '{% do {foo: y} = obj %}{{ y }}'; + $twig = $this->getEnvironment(true, [], ['index' => $template], ['do'], [], [], ['Twig\Tests\Extension\FooObject' => 'foo']); + try { + $twig->load('index')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception if an unallowed method is called via destructuring'); + } catch (SecurityNotAllowedMethodError $e) { + $this->assertSame('Twig\Tests\Extension\FooObject', $e->getClassName()); + $this->assertSame('foo', $e->getMethodName()); + } + } + public function testSandboxAllowFunction() { $twig = $this->getEnvironment(true, [], self::$templates, [], [], [], [], ['cycle']);