Skip to content

Commit 15aa49e

Browse files
committed
Add more test for sandbox
1 parent 0fc3341 commit 15aa49e

File tree

1 file changed

+54
-2
lines changed

1 file changed

+54
-2
lines changed

tests/Extension/SandboxTest.php

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ protected function setUp(): void
4141
'1_basic7' => '{{ cycle(["foo","bar"], 1) }}',
4242
'1_basic8' => '{{ obj.getfoobar }}{{ obj.getFooBar }}',
4343
'1_basic9' => '{{ obj.foobar }}{{ obj.fooBar }}',
44+
'1_basic10' => '{{ obj.baz }}',
45+
'1_basic11' => '{{ obj.xyz }}',
46+
'1_basic12' => '{{ obj.bac }}',
4447
'1_basic' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}',
4548
'1_layout' => '{% block content %}{% endblock %}',
4649
'1_child' => "{% extends \"1_layout\" %}\n{% block content %}\n{{ \"a\"|json_encode }}\n{% endblock %}",
@@ -326,6 +329,35 @@ public function testSandboxAllowFunctionsCaseInsensitive()
326329
}
327330
}
328331

332+
public function testSandboxRunGetterInsteadOfUnallowedProperty()
333+
{
334+
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array(FooObject::class => 'getBaz'));
335+
FooObject::reset();
336+
$this->assertEquals('baz', $twig->load('1_basic10')->render(self::$params), 'Sandbox allow some methods');
337+
$this->assertEquals(1, FooObject::$called['getBaz'], 'Sandbox only calls method getBaz');
338+
}
339+
340+
public function testSandboxRunCallInsteadOfUnallowedProperty()
341+
{
342+
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array(FooObject::class => '__call'));
343+
FooObject::reset();
344+
$this->assertEquals('xyz', $twig->load('1_basic11')->render(self::$params), 'Sandbox allow a method (__call())');
345+
$this->assertEquals(1, FooObject::$called['__call'], 'Sandbox only calls method __call');
346+
}
347+
348+
public function testSandboxRunCallInsteadOfUnallowedPropertyAndThrowException()
349+
{
350+
$twig = $this->getEnvironment(true, array(), self::$templates, [], [], [FooObject::class => '__call']);
351+
FooObject::reset();
352+
try {
353+
$twig->load('1_basic12')->render(self::$params);
354+
$this->fail('Sandbox throws a SecurityError exception if an unallowed property is called in the template through a method (__call)');
355+
} catch (SecurityError $e) {
356+
$this->assertEquals(sprintf('Calling "bac" property on a "%s" object is not allowed.', FooObject::class), $e->getRawMessage());
357+
$this->assertEquals(1, FooObject::$called['__call'], 'Sandbox only calls method __call');
358+
}
359+
}
360+
329361
public function testSandboxLocallySetForAnInclude()
330362
{
331363
self::$templates = [
@@ -418,13 +450,17 @@ protected function getEnvironment($sandboxed, $options, $templates, $tags = [],
418450

419451
class FooObject
420452
{
421-
public static $called = ['__toString' => 0, 'foo' => 0, 'getFooBar' => 0];
453+
public static $called = ['__call' => 0, '__toString' => 0, 'foo' => 0, 'getBaz' => 0, 'getFooBar' => 0];
422454

423455
public $bar = 'bar';
424456

457+
public $baz = 'baz';
458+
459+
public $bac = 'bac';
460+
425461
public static function reset()
426462
{
427-
self::$called = ['__toString' => 0, 'foo' => 0, 'getFooBar' => 0];
463+
self::$called = ['__call' => 0, '__toString' => 0, 'foo' => 0, 'getBaz' => 0, 'getFooBar' => 0];
428464
}
429465

430466
public function __toString()
@@ -452,4 +488,20 @@ public function getAnotherFooObject()
452488
{
453489
return new self();
454490
}
491+
492+
public function getBaz()
493+
{
494+
++self::$called['getBaz'];
495+
return $this->baz;
496+
}
497+
498+
public function __call($name, $arguments)
499+
{
500+
++self::$called['__call'];
501+
if ('bac' === strtolower($name)) {
502+
throw new \BadMethodCallException('bac() method is not allowed');
503+
}
504+
505+
return $name;
506+
}
455507
}

0 commit comments

Comments
 (0)