fixed __toString() calls when sandbox is enabled
authorFabien Potencier <fabien.potencier@gmail.com>
Fri, 26 Nov 2010 21:15:05 +0000 (22:15 +0100)
committerFabien Potencier <fabien.potencier@gmail.com>
Fri, 26 Nov 2010 21:15:05 +0000 (22:15 +0100)
lib/Twig/Node/SandboxedPrint.php
lib/Twig/NodeVisitor/Sandbox.php
test/Twig/Tests/Extension/SandboxTest.php
test/Twig/Tests/Node/SandboxedPrintTest.php

index 773b0f3..34db421 100644 (file)
@@ -36,17 +36,18 @@ class Twig_Node_SandboxedPrint extends Twig_Node_Print
     {
         $compiler
             ->addDebugInfo($this)
-            ->write('if ($this->env->hasExtension(\'sandbox\') && is_object(')
+            ->write('$_tmp = ')
             ->subcompile($this->getNode('expr'))
-            ->raw(')) {'."\n")
+            ->raw(";\n")
+            ->write('if (is_object(')
+            ->raw('$_tmp)) {'."\n")
             ->indent()
             ->write('$this->env->getExtension(\'sandbox\')->checkMethodAllowed(')
-            ->subcompile($this->getNode('expr'))
-            ->raw(', \'__toString\');'."\n")
+            ->raw('$_tmp, \'__toString\');'."\n")
             ->outdent()
             ->write('}'."\n")
+            ->write('echo ')
+            ->raw("\$_tmp;\n")
         ;
-
-        parent::compile($compiler);
     }
 }
index 77a507b..542b730 100644 (file)
@@ -48,8 +48,8 @@ class Twig_NodeVisitor_Sandbox implements Twig_NodeVisitorInterface
                 $this->filters[] = $node->getNode('filter')->getAttribute('value');
             }
 
-            // look for simple print statements ({{ article }})
-            if ($node instanceof Twig_Node_Print && $node->getNode('expr') instanceof Twig_Node_Expression_Name) {
+            // wrap print to check __toString() calls
+            if ($node instanceof Twig_Node_Print) {
                 return new Twig_Node_SandboxedPrint($node);
             }
         }
index a939ffd..33692ab 100644 (file)
@@ -18,6 +18,7 @@ class Twig_Tests_Extension_SandboxTest extends PHPUnit_Framework_TestCase
         self::$params = array(
             'name' => 'Fabien',
             'obj'  => new Object(),
+            'arr'  => array('obj' => new Object()),
         );
 
         self::$templates = array(
@@ -26,6 +27,7 @@ class Twig_Tests_Extension_SandboxTest extends PHPUnit_Framework_TestCase
             '1_basic3' => '{% if name %}foo{% endif %}',
             '1_basic4' => '{{ obj.bar }}',
             '1_basic5' => '{{ obj }}',
+            '1_basic6' => '{{ arr.obj }}',
             '1_basic'  => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}',
         );
     }
@@ -70,6 +72,13 @@ class Twig_Tests_Extension_SandboxTest extends PHPUnit_Framework_TestCase
         } catch (Twig_Sandbox_SecurityError $e) {
         }
 
+        $twig = $this->getEnvironment(true, self::$templates);
+        try {
+            $twig->loadTemplate('1_basic6')->render(self::$params);
+            $this->fail('Sandbox throws a SecurityError exception if an unallowed method (__toString()) is called in the template');
+        } catch (Twig_Sandbox_SecurityError $e) {
+        }
+
         $twig = $this->getEnvironment(true, self::$templates, array(), array(), array('Object' => 'foo'));
         $this->assertEquals('foo', $twig->loadTemplate('1_basic1')->render(self::$params), 'Sandbox allow some methods');
 
index a326005..3e53b6e 100644 (file)
@@ -40,10 +40,11 @@ class Twig_Tests_Node_SandboxedPrintTest extends Twig_Tests_Node_TestCase
 
         $node = new Twig_Node_Print(new Twig_Node_Expression_Constant('foo', 0), 0);
         $tests[] = array(new Twig_Node_SandboxedPrint($node), <<<EOF
-if (\$this->env->hasExtension('sandbox') && is_object("foo")) {
-    \$this->env->getExtension('sandbox')->checkMethodAllowed("foo", '__toString');
+\$_tmp = "foo";
+if (is_object(\$_tmp)) {
+    \$this->env->getExtension('sandbox')->checkMethodAllowed(\$_tmp, '__toString');
 }
-echo "foo";
+echo \$_tmp;
 EOF
         );