mirror of
https://github.com/twigphp/Twig.git
synced 2026-10-09 21:35:40 +00:00
bug #4918 Check that the use tag is allowed before resolving trait templates (fabpot)
This PR was merged into the 3.x branch.
Discussion
----------
Check that the use tag is allowed before resolving trait templates
Commits
-------
18863f0371 Check that the use tag is allowed before resolving trait templates
This commit is contained in:
@@ -15,6 +15,9 @@ use Twig\Attribute\YieldReady;
|
||||
use Twig\Compiler;
|
||||
|
||||
/**
|
||||
* Wires the security checker at the very top of the template constructor, as
|
||||
* the constructor resolves `use` traits before the sandbox could check them.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
#[YieldReady]
|
||||
@@ -26,7 +29,7 @@ class CheckSecurityCallNode extends Node
|
||||
public function compile(Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
->write("\$this->sandbox = \$this->extensions[SandboxExtension::class]->getChecker();\n")
|
||||
->write("\$this->sandbox = \$env->getExtension(SandboxExtension::class)->getChecker();\n")
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,32 @@ class CheckSecurityNode extends Node
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
{
|
||||
if (isset($this->usedTags['use'])) {
|
||||
$compiler
|
||||
->write("\n")
|
||||
->write("protected function checkTraitsAllowed(): void\n")
|
||||
->write("{\n")
|
||||
->indent()
|
||||
->write("if (!\$this->sandbox->isSandboxed(\$this->source)) {\n")
|
||||
->indent()
|
||||
->write("return;\n")
|
||||
->outdent()
|
||||
->write("}\n\n")
|
||||
->write("try {\n")
|
||||
->indent()
|
||||
->write("\$this->sandbox->checkSecurity(['use'], [], [], [], \$this->source);\n")
|
||||
->outdent()
|
||||
->write("} catch (SecurityNotAllowedTagError \$e) {\n")
|
||||
->indent()
|
||||
->write('$e->setTemplateLine(')->repr($this->usedTags['use'])->raw(");\n\n")
|
||||
->write("throw \$e;\n")
|
||||
->outdent()
|
||||
->write("}\n")
|
||||
->outdent()
|
||||
->write("}\n")
|
||||
;
|
||||
}
|
||||
|
||||
$compiler
|
||||
->write("\n")
|
||||
->write("public function ensureSecurityChecked(): void\n")
|
||||
|
||||
@@ -218,7 +218,8 @@ final class ModuleNode extends Node implements CoercesChildrenToStringInterface
|
||||
|
||||
$countTraits = \count($this->getNode('traits'));
|
||||
if ($countTraits) {
|
||||
// traits
|
||||
$compiler->write("\$this->ensureTraitsAllowed();\n\n");
|
||||
|
||||
foreach ($this->getNode('traits') as $i => $trait) {
|
||||
$node = $trait->getNode('template');
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ final class SandboxNodeVisitor implements NodeVisitorInterface
|
||||
if ($node instanceof ModuleNode) {
|
||||
$this->inAModule = false;
|
||||
|
||||
$node->setNode('constructor_end', new Nodes([new CheckSecurityCallNode(), $node->getNode('constructor_end')]));
|
||||
$node->setNode('constructor_start', new Nodes([new CheckSecurityCallNode(), $node->getNode('constructor_start')]));
|
||||
$node->setNode('class_end', new Nodes([new CheckSecurityNode($this->filters, $this->tags, $this->functions, $this->tests), $node->getNode('class_end')]));
|
||||
}
|
||||
|
||||
|
||||
@@ -508,6 +508,31 @@ abstract class Template
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the "use" tag against the sandbox policy.
|
||||
*
|
||||
* The constructor resolves "use" traits eagerly, which reaches the loader,
|
||||
* so that tag alone is checked here; the rest of the policy still runs at
|
||||
* render time.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function ensureTraitsAllowed(): void
|
||||
{
|
||||
try {
|
||||
$this->checkTraitsAllowed();
|
||||
} catch (\Throwable $e) {
|
||||
$this->handleException($e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function checkTraitsAllowed(): void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto-generated method to display the template with the given context.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user