Skip the sandbox __toString check on arguments whose PHP parameter type cannot implicitly coerce to string

This commit is contained in:
Fabien Potencier
2026-06-01 09:31:30 +02:00
parent 4e58cb22e5
commit 6d5ef30436
8 changed files with 682 additions and 42 deletions
+37 -1
View File
@@ -11,6 +11,7 @@
namespace Twig\Util;
use Twig\Node\Expression\CallExpression;
use Twig\TwigCallableInterface;
/**
@@ -25,7 +26,7 @@ final class ReflectionCallable
private $name;
public function __construct(
TwigCallableInterface $twigCallable,
private TwigCallableInterface $twigCallable,
) {
$callable = $twigCallable->getCallable();
if (\is_string($callable) && false !== $pos = strpos($callable, '::')) {
@@ -80,6 +81,41 @@ final class ReflectionCallable
return $this->reflector;
}
/**
* Returns the PHP parameters that map to the callable's template-level
* arguments.
*
* The parameters Twig injects automatically (the piped input value when
* $stripInput is true, then needs_charset/environment/context/is_sandboxed)
* and the bound arguments are stripped.
*
* @return list<\ReflectionParameter>
*/
public function getTwigParameters(bool $stripInput = false): array
{
$parameters = $this->reflector->getParameters();
if ($stripInput) {
array_shift($parameters);
}
if ($this->twigCallable->needsCharset()) {
array_shift($parameters);
}
if ($this->twigCallable->needsEnvironment()) {
array_shift($parameters);
}
if ($this->twigCallable->needsContext()) {
array_shift($parameters);
}
if (CallExpression::needsIsSandboxed($this->twigCallable)) {
array_shift($parameters);
}
foreach ($this->twigCallable->getArguments() as $argument) {
array_shift($parameters);
}
return array_values($parameters);
}
/**
* @return callable
*/