Repository: twigphp/Twig (php)

Issue:
Attempted to call an undefined method named "checkSecurity"
Hello, 

it's seem what something is broken when i updated in twig 1.44

<pre>Attempted to call an undefined method named "checkSecurity" of class "__TwigTemplate_ab8c5b3634ec2ea857069474b49ae5f5b2f484499df40afbe2063e28cae810c4".
500 Internal Server Error - UndefinedMethodException

Stack Trace
in /var/www/vhosts/vendor/twig/twig/src/Extension/CoreExtension.php at line 1572  -
    // if a Template instance is passed, it might have been instantiated outside of a sandbox, check security
    if ($template instanceof TemplateWrapper || $template instanceof Template) {
        $template->unwrap()->checkSecurity();
    }
    $loaded = null;
</pre>

happen with a {{ include(template_from_string("something")) }}

Pull request:
Fix "include(template_from_string())" when not using a sandbox
Closed #3411


Patch:
diff --git a/CHANGELOG b/CHANGELOG
index f4f447fd..b02b72a1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,6 @@
 # 1.44.1 (2020-XX-XX)
 
- * n/a
+ * Fix "include(template_from_string())"
 
 # 1.44.0 (2020-10-21)
 
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 3eb5cdaa..9af92f46 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -12,9 +12,4 @@
   <listeners>
     <listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener" />
   </listeners>
-  <coverage>
-    <include>
-      <directory suffix=".php">./src/</directory>
-    </include>
-  </coverage>
 </phpunit>
diff --git a/src/Extension/CoreExtension.php b/src/Extension/CoreExtension.php
index e98f9e99..b57f9a11 100644
--- a/src/Extension/CoreExtension.php
+++ b/src/Extension/CoreExtension.php
@@ -1565,11 +1565,13 @@ function twig_include(Environment $env, $context, $template, $variables = [], $w
         if (!$alreadySandboxed = $sandbox->isSandboxed()) {
             $sandbox->enableSandbox();
         }
-    }
 
-    // if a Template instance is passed, it might have been instantiated outside of a sandbox, check security
-    if ($template instanceof TemplateWrapper || $template instanceof Template) {
-        $template->unwrap()->checkSecurity();
+        foreach ((\is_array($template) ? $template : [$template]) as $name) {
+            // if a Template instance is passed, it might have been instantiated outside of a sandbox, check security
+            if ($name instanceof TemplateWrapper || $name instanceof Template) {
+                $name->unwrap()->checkSecurity();
+            }
+        }
     }
 
     $loaded = null;


Test patch:
diff --git a/tests/Extension/SandboxTest.php b/tests/Extension/SandboxTest.php
index caa543aa..a1a989f7 100644
--- a/tests/Extension/SandboxTest.php
+++ b/tests/Extension/SandboxTest.php
@@ -45,7 +45,8 @@ class SandboxTest extends \PHPUnit\Framework\TestCase
             '1_layout' => '{% block content %}{% endblock %}',
             '1_child' => "{% extends \"1_layout\" %}\n{% block content %}\n{{ \"a\"|json_encode }}\n{% endblock %}",
             '1_include' => '{{ include("1_basic1", sandboxed=true) }}',
-            '1_basic2_include_template_from_string' => '{{ include(template_from_string("{{ name|upper }}"), sandboxed=true) }}',
+            '1_basic2_include_template_from_string_sandboxed' => '{{ include(template_from_string("{{ name|upper }}"), sandboxed=true) }}',
+            '1_basic2_include_template_from_string' => '{{ include(template_from_string("{{ name|upper }}")) }}',
             '1_range_operator' => '{{ (1..2)[0] }}',
             '1_syntax_error_wrapper' => '{% sandbox %}{% include "1_syntax_error" %}{% endsandbox %}',
             '1_syntax_error' => '{% syntax error }}',
@@ -92,10 +93,43 @@ class SandboxTest extends \PHPUnit\Framework\TestCase
         }
     }
 
-    public function testSandboxUnallowedFilterWithIncludeTemplateFromString()
+    public function testSandboxGloballyFalseUnallowedFilterWithIncludeTemplateFromStringSandboxed()
     {
         $twig = $this->getEnvironment(false, [], self::$templates);
         $twig->addExtension(new StringLoaderExtension());
+        try {
+            $twig->load('1_basic2_include_template_from_string_sandboxed')->render(self::$params);
+            $this->fail('Sandbox throws a SecurityError exception if an unallowed filter is called');
+        } catch (SecurityError $e) {
+            $this->assertInstanceOf('\Twig\Sandbox\SecurityNotAllowedFilterError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedFilterError');
+            $this->assertEquals('upper', $e->getFilterName(), 'Exception should be raised on the "upper" filter');
+        }
+    }
+
+    public function testSandboxGloballyTrueUnallowedFilterWithIncludeTemplateFromStringSandboxed()
+    {
+        $twig = $this->getEnvironment(true, [], self::$templates, [], [], [], [], ['include', 'template_from_string']);
+        $twig->addExtension(new StringLoaderExtension());
+        try {
+            $twig->load('1_basic2_include_template_from_string_sandboxed')->render(self::$params);
+            $this->fail('Sandbox throws a SecurityError exception if an unallowed filter is called');
+        } catch (SecurityError $e) {
+            $this->assertInstanceOf('\Twig\Sandbox\SecurityNotAllowedFilterError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedFilterError');
+            $this->assertEquals('upper', $e->getFilterName(), 'Exception should be raised on the "upper" filter');
+        }
+    }
+
+    public function testSandboxGloballyFalseUnallowedFilterWithIncludeTemplateFromStringNotSandboxed()
+    {
+        $twig = $this->getEnvironment(false, [], self::$templates);
+        $twig->addExtension(new StringLoaderExtension());
+        $this->assertSame('FABIEN', $twig->load('1_basic2_include_template_from_string')->render(self::$params));
+    }
+
+    public function testSandboxGloballyTrueUnallowedFilterWithIncludeTemplateFromStringNotSandboxed()
+    {
+        $twig = $this->getEnvironment(true, [], self::$templates, [], [], [], [], ['include', 'template_from_string']);
+        $twig->addExtension(new StringLoaderExtension());
         try {
             $twig->load('1_basic2_include_template_from_string')->render(self::$params);
             $this->fail('Sandbox throws a SecurityError exception if an unallowed filter is called');
diff --git a/tests/Extension/StringLoaderExtensionTest.php b/tests/Extension/StringLoaderExtensionTest.php
new file mode 100644
index 00000000..c4b28591
--- /dev/null
+++ b/tests/Extension/StringLoaderExtensionTest.php
@@ -0,0 +1,26 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Twig\Tests\Extension;
+
+use Twig\Environment;
+use PHPUnit\Framework\TestCase;
+use Twig\Extension\StringLoaderExtension;
+
+class StringLoaderExtensionTest extends TestCase
+{
+    public function testIncludeWithTemplateStringAndNoSandbox()
+    {
+        $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface'));
+        $twig->addExtension(new StringLoaderExtension());
+        $this->assertSame('something', twig_include($twig, [], twig_template_from_string($twig, "something")));
+    }
+}