mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-16 04:16:28 +00:00
Fix merge conflict resolution
This commit is contained in:
@@ -12,7 +12,6 @@
|
||||
namespace Twig\Tests\Extension;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
|
||||
use Twig\Environment;
|
||||
use Twig\Extension\SandboxExtension;
|
||||
use Twig\Loader\ArrayLoader;
|
||||
@@ -21,8 +20,6 @@ use Twig\Sandbox\SecurityNotAllowedFunctionError;
|
||||
use Twig\Sandbox\SecurityNotAllowedTagError;
|
||||
use Twig\Sandbox\SecurityPolicy;
|
||||
use Twig\Sandbox\SecurityPolicyInterface;
|
||||
use Twig\Sandbox\SourcePolicyInterface;
|
||||
use Twig\Source;
|
||||
|
||||
/**
|
||||
* Regression tests for the sandbox filter/tag/function allow-list bypass that
|
||||
@@ -35,8 +32,6 @@ use Twig\Source;
|
||||
*/
|
||||
class SandboxStateChangeTest extends TestCase
|
||||
{
|
||||
use ExpectDeprecationTrait;
|
||||
|
||||
public function testEnableSandboxAfterFirstRender()
|
||||
{
|
||||
[$twig, $sandbox] = $this->build(['t' => '{{ "foo"|upper }}'], new SecurityPolicy(allowedFilters: []), false);
|
||||
@@ -99,32 +94,6 @@ class SandboxStateChangeTest extends TestCase
|
||||
$this->assertSame('FOO', $twig->render('t'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testSourcePolicyDecisionFlip()
|
||||
{
|
||||
$this->expectDeprecation('Since twig/twig 3.27.0: The "Twig\Sandbox\SourcePolicyInterface" interface is deprecated with no replacement, do not pass an instance to "Twig\Extension\SandboxExtension".');
|
||||
|
||||
$sourcePolicy = new class implements SourcePolicyInterface {
|
||||
public array $sandboxFor = [];
|
||||
|
||||
public function enableSandbox(Source $source): bool
|
||||
{
|
||||
return \in_array($source->getName(), $this->sandboxFor, true);
|
||||
}
|
||||
};
|
||||
|
||||
[$twig] = $this->build(['t' => '{{ "foo"|upper }}'], new SecurityPolicy(allowedFilters: []), false, $sourcePolicy);
|
||||
|
||||
$this->assertSame('FOO', $twig->render('t'));
|
||||
|
||||
$sourcePolicy->sandboxFor = ['t'];
|
||||
|
||||
$this->expectException(SecurityNotAllowedFilterError::class);
|
||||
$twig->render('t');
|
||||
}
|
||||
|
||||
public function testPreWarmedParentTemplateThroughExtends()
|
||||
{
|
||||
$templates = [
|
||||
@@ -194,31 +163,6 @@ class SandboxStateChangeTest extends TestCase
|
||||
$twig->render('caller.twig');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testSandboxTagAroundIncludeOfPreWarmedTemplate()
|
||||
{
|
||||
$this->expectDeprecation('Since twig/twig 3.15: The "sandbox" tag is deprecated in "wrapper" at line 1.');
|
||||
|
||||
$templates = [
|
||||
'wrapper' => '{% sandbox %}{% include "user" %}{% endsandbox %}',
|
||||
'user' => '{% extends "shared" %}{% block c %}user{% endblock %}',
|
||||
'shared' => '{% block c %}{% endblock %}{{ "ok"|upper }}',
|
||||
];
|
||||
$policy = new SecurityPolicy(
|
||||
allowedTags: ['extends', 'block', 'include'],
|
||||
allowedFilters: ['escape'],
|
||||
);
|
||||
[$twig] = $this->build($templates, $policy, false);
|
||||
|
||||
$this->assertSame('OK', $twig->render('shared'));
|
||||
|
||||
$this->expectException(SecurityNotAllowedFilterError::class);
|
||||
$this->expectExceptionMessage('Filter "upper" is not allowed');
|
||||
$twig->render('wrapper');
|
||||
}
|
||||
|
||||
public function testTagBypassThroughPreWarmedParent()
|
||||
{
|
||||
$templates = [
|
||||
@@ -392,10 +336,10 @@ class SandboxStateChangeTest extends TestCase
|
||||
/**
|
||||
* @return array{0: Environment, 1: SandboxExtension}
|
||||
*/
|
||||
private function build(array $templates, SecurityPolicyInterface $policy, bool $sandboxed, ?SourcePolicyInterface $sourcePolicy = null): array
|
||||
private function build(array $templates, SecurityPolicyInterface $policy, bool $sandboxed): array
|
||||
{
|
||||
$twig = new Environment(new ArrayLoader($templates), ['cache' => false, 'autoescape' => false]);
|
||||
$sandbox = new SandboxExtension($policy, $sandboxed, $sourcePolicy);
|
||||
$sandbox = new SandboxExtension($policy, $sandboxed);
|
||||
$twig->addExtension($sandbox);
|
||||
|
||||
return [$twig, $sandbox];
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace Twig\Tests\Extension;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Twig\Environment;
|
||||
use Twig\Error\RuntimeError;
|
||||
use Twig\Error\SyntaxError;
|
||||
use Twig\Extension\SandboxExtension;
|
||||
use Twig\Extension\StringLoaderExtension;
|
||||
@@ -980,9 +981,7 @@ EOF
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getStringableTraversableBypassTemplates
|
||||
*/
|
||||
#[DataProvider('getStringableTraversableBypassTemplates')]
|
||||
public function testSandboxBlocksToStringInStringableTraversable(string $template)
|
||||
{
|
||||
$twig = $this->getEnvironment(
|
||||
@@ -1009,43 +1008,6 @@ EOF
|
||||
yield 'replace' => ['{{ "__toString"|replace(stringable_iterator_map) }}'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*
|
||||
* @dataProvider getStringableTraversableBypassTemplates
|
||||
*/
|
||||
public function testSourcePolicySandboxBlocksToStringInStringableTraversable(string $template)
|
||||
{
|
||||
$this->expectDeprecation('Since twig/twig 3.27.0: The "Twig\Sandbox\SourcePolicyInterface" interface is deprecated with no replacement, do not pass an instance to "Twig\Extension\SandboxExtension".');
|
||||
|
||||
$sourcePolicy = new class implements SourcePolicyInterface {
|
||||
public function enableSandbox(Source $source): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
$twig = $this->getEnvironment(
|
||||
false,
|
||||
[],
|
||||
['index' => $template],
|
||||
[],
|
||||
['join', 'replace'],
|
||||
['Twig\Tests\Extension\StringableTraversableObject' => ['__tostring']],
|
||||
[],
|
||||
[],
|
||||
$sourcePolicy,
|
||||
);
|
||||
|
||||
try {
|
||||
$twig->load('index')->render(self::$params);
|
||||
$this->fail('Sandbox should block __toString on objects yielded by a Stringable+Traversable container under a SourcePolicyInterface-only sandbox.');
|
||||
} catch (SecurityNotAllowedMethodError $e) {
|
||||
$this->assertSame('Twig\Tests\Extension\FooObject', $e->getClassName());
|
||||
$this->assertSame('__tostring', $e->getMethodName());
|
||||
}
|
||||
}
|
||||
|
||||
public function testSandboxAllowsPrintingStringableTraversableWhenToStringAllowed()
|
||||
{
|
||||
// Printing the container itself yields its `__toString()` value. The
|
||||
@@ -1066,9 +1028,7 @@ EOF
|
||||
$this->assertSame('stringable-traversable', $twig->load('index')->render($params));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getCyclicTraversableTemplates
|
||||
*/
|
||||
#[DataProvider('getCyclicTraversableTemplates')]
|
||||
public function testSandboxHandlesCyclicTraversableWithoutStackOverflow(string $template)
|
||||
{
|
||||
// A self-referencing IteratorAggregate must not cause the sandbox policy
|
||||
@@ -1095,56 +1055,6 @@ EOF
|
||||
yield 'spread' => ['{{ ["a", ...obj]|join(",") }}'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testSourcePolicySandboxBlocksToStringInTraversableJoin()
|
||||
{
|
||||
$this->expectDeprecation('Since twig/twig 3.27.0: The "Twig\Sandbox\SourcePolicyInterface" interface is deprecated with no replacement, do not pass an instance to "Twig\Extension\SandboxExtension".');
|
||||
|
||||
$sourcePolicy = new class implements SourcePolicyInterface {
|
||||
public function enableSandbox(Source $source): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
$twig = $this->getEnvironment(false, [], ['index' => '{{ iterator|join(", ") }}'], [], ['join'], [], [], [], $sourcePolicy);
|
||||
|
||||
try {
|
||||
$twig->load('index')->render(self::$params);
|
||||
$this->fail('Sandbox should block __toString on objects contained in a Traversable passed to the "join" filter (SourcePolicyInterface).');
|
||||
} catch (SecurityNotAllowedMethodError $e) {
|
||||
$this->assertSame('Twig\Tests\Extension\FooObject', $e->getClassName());
|
||||
$this->assertSame('__tostring', $e->getMethodName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testSourcePolicySandboxBlocksToStringInTraversableReplace()
|
||||
{
|
||||
$this->expectDeprecation('Since twig/twig 3.27.0: The "Twig\Sandbox\SourcePolicyInterface" interface is deprecated with no replacement, do not pass an instance to "Twig\Extension\SandboxExtension".');
|
||||
|
||||
$sourcePolicy = new class implements SourcePolicyInterface {
|
||||
public function enableSandbox(Source $source): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
$twig = $this->getEnvironment(false, [], ['index' => '{{ "__toString"|replace(iterator_map) }}'], [], ['replace'], [], [], [], $sourcePolicy);
|
||||
|
||||
try {
|
||||
$twig->load('index')->render(self::$params);
|
||||
$this->fail('Sandbox should block __toString on objects contained in a Traversable passed to the "replace" filter (SourcePolicyInterface).');
|
||||
} catch (SecurityNotAllowedMethodError $e) {
|
||||
$this->assertSame('Twig\Tests\Extension\FooObject', $e->getClassName());
|
||||
$this->assertSame('__tostring', $e->getMethodName());
|
||||
}
|
||||
}
|
||||
|
||||
public function testSandboxPreservesTraversableArgumentIdentity()
|
||||
{
|
||||
// Regression for https://github.com/twigphp/Twig/issues/4820:
|
||||
@@ -1199,9 +1109,7 @@ EOF
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getSafePhpTypesSkipToStringWrap
|
||||
*/
|
||||
#[DataProvider('getSafePhpTypesSkipToStringWrap')]
|
||||
public function testSafePhpParamTypesSkipToStringWrap(string $template, callable $func, array $params): void
|
||||
{
|
||||
// The sandbox visitor must not wrap arguments whose target PHP
|
||||
@@ -1252,9 +1160,7 @@ EOF
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getUnsafePhpTypesStillWrap
|
||||
*/
|
||||
#[DataProvider('getUnsafePhpTypesStillWrap')]
|
||||
public function testUnsafePhpParamTypesStillWrap(string $template, callable $func, array $params): void
|
||||
{
|
||||
// Conversely, an unsafe parameter type (`mixed`, untyped, `string`,
|
||||
@@ -1284,9 +1190,7 @@ EOF
|
||||
yield 'Stringable param' => ['{{ unsafe_fn(obj) }}', static fn (\Stringable $x) => (string) $x, $params];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getOpenPhpTypesStillWrap
|
||||
*/
|
||||
#[DataProvider('getOpenPhpTypesStillWrap')]
|
||||
public function testOpenPhpParamTypesStillWrap(callable $func, object $obj, string $class): void
|
||||
{
|
||||
// Interfaces and non-final classes are "open": a Stringable subtype
|
||||
|
||||
@@ -11,14 +11,13 @@
|
||||
|
||||
namespace Twig\Tests\Util;
|
||||
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Twig\Util\CallableParameters;
|
||||
|
||||
class CallableParametersTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideTypes
|
||||
*/
|
||||
#[DataProvider('provideTypes')]
|
||||
public function testIsStringCoercionSafe(?\ReflectionType $type, bool $expected, ?\ReflectionClass $scope = null): void
|
||||
{
|
||||
$this->assertSame($expected, CallableParameters::isStringCoercionSafe($type, $scope));
|
||||
|
||||
Reference in New Issue
Block a user