Commit Graph

7548 Commits

Author SHA1 Message Date
Fabien Potencier 3868bac531 Avoid allocating a normalized copy when counting newlines without carriage returns 2026-06-05 20:33:28 +02:00
Fabien Potencier a82782ac30 Report columns in syntax errors 2026-06-05 20:28:45 +02:00
Fabien Potencier 4943bb405c Track the source offset of each token 2026-06-05 20:28:45 +02:00
Fabien Potencier afad02326d minor #4662 CoreExtension::getAttribute: small improvement regarding getter/isser/hasser (gharlan)
This PR was merged into the 3.x branch.

Discussion
----------

CoreExtension::getAttribute: small improvement regarding getter/isser/hasser

For a getter method like `getFirstName` it is common to call it in twig via `person.firstName`.
But at the moment twig is adding these variants to the class method cache: `getFirstName`, `getfirstname`, `FirstName` and `firstname`.
So when resolving the name, it uses the first `elseif` here with additional `strtolower` call, because `firstName` is missing:

https://github.com/twigphp/Twig/blob/403bd9d73c2a010e5b26689f2f2eb9d7ddf391af/src/Extension/CoreExtension.php#L1863-L1867

This PR replaces `FirstName` with `firstName` in the method cache.
So `person.firstName` is resolved via first `if` branch (but `person.FirstName` would use the `elseif` with `strtolower` now).

Commits
-------

45cd6ffe80 CoreExtension::getAttribute: small improvement regarding getter/isser/hasser
2026-06-04 22:28:58 +02:00
Fabien Potencier 379df77252 bug #4825 Make the include() function return a Markup object (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Make the include() function return a Markup object

Closes #4754

Commits
-------

a3eda4b1fd Make the include() function return a Markup object
2026-06-04 21:32:19 +02:00
Fabien Potencier a3eda4b1fd Make the include() function return a Markup object 2026-06-04 21:32:12 +02:00
Fabien Potencier ecf0ebf78b bug #4830 Fix nested block() resolution when a directly rendered block calls parent() (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Fix nested block() resolution when a directly rendered block calls parent()

Closes #3321

Commits
-------

279fe13b22 Fix nested block() resolution when a directly rendered block calls parent()
2026-06-04 21:30:37 +02:00
Fabien Potencier 279fe13b22 Fix nested block() resolution when a directly rendered block calls parent() 2026-06-03 22:13:40 +02:00
Fabien Potencier 2171127676 Fix nested block() resolution when a directly rendered block calls parent() 2026-06-03 22:09:09 +02:00
Fabien Potencier a0093cd699 minor #4827 Document {#--#} as the replacement for the deprecated spaceless filter (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Document {#--#} as the replacement for the deprecated spaceless filter

Closes #4442

Commits
-------

c29877f54a Document {#--#} as the replacement for the deprecated spaceless filter
2026-06-03 22:03:07 +02:00
Fabien Potencier 1bdc760cff bug #4828 Stop reporting a skipped test in IntegrationTestCase when there is no legacy test to run (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Stop reporting a skipped test in IntegrationTestCase when there is no legacy test to run

Closes #4635

Commits
-------

86076c87a6 Stop reporting a skipped test in IntegrationTestCase when there is no legacy test to run
2026-06-03 22:02:35 +02:00
Fabien Potencier b52f6d9927 minor #4829 Document storing an enum in a variable to avoid repeating its FQCN (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Document storing an enum in a variable to avoid repeating its FQCN

Closes #4646

Commits
-------

e1178abfa1 Document storing an enum in a variable to avoid repeating its FQCN
2026-06-03 22:00:02 +02:00
Fabien Potencier e1178abfa1 Document storing an enum in a variable to avoid repeating its FQCN 2026-06-03 21:58:29 +02:00
Fabien Potencier 86076c87a6 Stop reporting a skipped test in IntegrationTestCase when there is no legacy test to run 2026-06-03 20:07:23 +02:00
Fabien Potencier c29877f54a Document {#--#} as the replacement for the deprecated spaceless filter 2026-06-03 20:00:30 +02:00
Fabien Potencier 1a2f2ea0a3 bug #4824 Cast printed expressions to string so values that cannot be converted to a string (arrays, non-Stringable objects, ...) report a usable stack trace at the print location (stof, fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Cast printed expressions to string so values that cannot be converted to a string (arrays, non-`Stringable` objects, ...) report a usable stack trace at the print location

Closes #4765
Closes #4780
Closes #4644

Is it what you had in mind `@stof`?

Commits
-------

89f886e324 Skip the string cast in PrintNode when the expression is already a string and add tests
86840f9351 Ensure PrintNode is yielding string content
2026-06-03 19:56:33 +02:00
Fabien Potencier 89f886e324 Skip the string cast in PrintNode when the expression is already a string and add tests 2026-06-03 19:56:27 +02:00
Christophe Coevoet 86840f9351 Ensure PrintNode is yielding string content 2026-06-03 19:56:11 +02:00
Fabien Potencier 4cc1afe067 feature #4826 Make IntegrationTestCase and NodeTestCase compatible with PHPUnit 11 (fabpot)
This PR was squashed before being merged into the 3.x branch.

Discussion
----------

Make IntegrationTestCase and NodeTestCase compatible with PHPUnit 11

Closes #4782

Commits
-------

8a4b77920a Add PHPUnit attributes alongside annotations to silence doc-comment metadata deprecations on PHPUnit 11
8b35934e68 Run the test suite against PHPUnit 11.3 in CI
ee8ab447d7 Make IntegrationTestCase and NodeTestCase compatible with PHPUnit 11
2026-06-03 19:45:14 +02:00
Fabien Potencier 8a4b77920a Add PHPUnit attributes alongside annotations to silence doc-comment metadata deprecations on PHPUnit 11 2026-06-03 18:26:39 +02:00
Fabien Potencier 8b35934e68 Run the test suite against PHPUnit 11.3 in CI 2026-06-03 18:21:23 +02:00
Fabien Potencier ee8ab447d7 Make IntegrationTestCase and NodeTestCase compatible with PHPUnit 11 2026-06-03 18:17:03 +02:00
Fabien Potencier 2a2f058f70 feature #4823 Skip the sandbox __toString check on arguments whose PHP parameter type cannot implicitly coerce to string (fabpot)
This PR was squashed before being merged into the 3.x branch.

Discussion
----------

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

The sandbox visitor currently wraps every argument of every Twig callable with `CheckToStringNode.

As an optimization, we are now only wrapping when needed (based on the callable type hints). This is a conservative approach (untyped, mixed, string, array, iterable, object, Stringable, Traversable, self/static/parent and unknown class names all keep wrapping).

Here is a concrete before/after for template `{{ demo(a, b) }}` under the sandbox, with the following signature on the PHP side `demo(int $a, string $b)`:

**Before**:

```php
    yield $this->sandbox->ensureToStringAllowed(
       $this->env->getFunction('demo')->getCallable()(
           $this->sandbox->ensureToStringAllowed(($context["a"] ?? null), 1, $this->source),
           $this->sandbox->ensureToStringAllowed(($context["b"] ?? null), 1, $this->source),
       ),
       1, $this->source,
   );
```

**After**

```php
   yield $this->sandbox->ensureToStringAllowed(
       $this->env->getFunction('demo')->getCallable()(
           ($context["a"] ?? null),                                                            // int: bare, skipped
           $this->sandbox->ensureToStringAllowed(($context["b"] ?? null), 1, $this->source),   // string: still wrapped
       ),
       1, $this->source,
   );
```

Commits
-------

6d5ef30436 Skip the sandbox `__toString` check on arguments whose PHP parameter type cannot implicitly coerce to string
2026-06-02 13:58:28 +02:00
Fabien Potencier 6d5ef30436 Skip the sandbox __toString check on arguments whose PHP parameter type cannot implicitly coerce to string 2026-06-02 13:58:24 +02:00
Fabien Potencier 4e58cb22e5 Fix CS 2026-06-01 09:00:03 +02:00
Fabien Potencier dc1db9ef63 Bump version 2026-05-30 19:09:51 +02:00
Fabien Potencier ae2071bffb Prepare the 3.27.1 release v3.27.1 2026-05-30 19:09:26 +02:00
Fabien Potencier 79884dee1c bug #4822 Fix inconsistent array access with a Stringable key (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Fix inconsistent array access with a Stringable key

Closes #4804

Commits
-------

8ec9530732 Fix inconsistent array access with a Stringable key
2026-05-29 11:45:30 +02:00
Fabien Potencier 8ec9530732 Fix inconsistent array access with a Stringable key 2026-05-29 10:06:57 +02:00
Fabien Potencier dfb5232d51 bug #4821 Preserve IteratorAggregate identity in sandbox __toString walker (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Preserve IteratorAggregate identity in sandbox __toString walker

Fixes #4820

It's not a full fix, but a quick one just that for the specific use case described in the issue. This is the simple case as IteratorAggregate instances can be iterated more than once (I suppose most such iterators don't have side effects).

Commits
-------

d25f98f45b Preserve IteratorAggregate identity in sandbox __toString walker
2026-05-29 09:34:05 +02:00
Fabien Potencier d25f98f45b Preserve IteratorAggregate identity in sandbox __toString walker 2026-05-29 09:31:03 +02:00
Fabien Potencier 118938b191 Fix tests 2026-05-29 09:30:54 +02:00
Fabien Potencier 86f3b3a1f2 Bump version 2026-05-27 15:06:12 +02:00
Fabien Potencier 04ae1bfe94 Prepare the 3.27.0 release v3.27.0 2026-05-27 15:05:51 +02:00
Fabien Potencier 99a10384ff security #558 Fix sandbox filter/tag/function allow-list bypass when sandbox state changes between renders (fabpot)
This PR was merged into the twig-3.x branch.

Discussion
----------

Fix sandbox filter/tag/function allow-list bypass when sandbox state changes between renders

Fixes #555

Commits
-------

23eb6eb126 Fix sandbox filter/tag/function allow-list bypass when sandbox state changes between renders
2026-05-27 14:59:52 +02:00
Fabien Potencier 23eb6eb126 Fix sandbox filter/tag/function allow-list bypass when sandbox state changes between renders 2026-05-27 14:59:42 +02:00
Fabien Potencier 7d55aa838c security #cve-2026-48805 Fix sandbox bypass in deprecated internal wrappers (fabpot)
This PR was merged into the twig-3.x branch.
2026-05-27 14:55:54 +02:00
Fabien Potencier 9fcf6906d7 security #552 Fix sandbox __toString policy bypass via dynamic mapping keys (fabpot)
This PR was squashed before being merged into the twig-3.x branch.

Discussion
----------

Fix sandbox __toString policy bypass via dynamic mapping keys

Fixes #548

Fixing this one introduces a new feature that I've decided to "keep" and document :)

Commits
-------

635cea4789 Document new support for any expression as a dynamic mapping key
9ff4101463 Fix sandbox __toString policy bypass via dynamic mapping keys
2026-05-27 14:55:08 +02:00
Fabien Potencier 635cea4789 Document new support for any expression as a dynamic mapping key 2026-05-27 14:54:58 +02:00
Fabien Potencier 9ff4101463 Fix sandbox __toString policy bypass via dynamic mapping keys 2026-05-27 14:54:34 +02:00
Fabien Potencier baebc46b67 security #535 Fix sandbox __toString bypasses via Traversable in join/replace filters and the in/not in operators (fabpot)
This PR was squashed before being merged into the twig-3.x branch.

Discussion
----------

Fix sandbox `__toString` bypasses via `Traversable` in `join`/`replace` filters and the `in`/`not in` operators

Fixes #512

Commits
-------

e3f66654b8 Fix deprecation notices in tests
475fb690ac Guard sandbox `__toString` walker against self-referencing iterables
e9e818cbfc Fix sandbox `__toString` bypass via `Stringable` + `Traversable` containers
8d6af0707b Fix sandbox `__toString` bypass via the `in` and `not in` operators
cc1e21a2a2 Fix sandbox __toString bypass via Traversable in join/replace filters
2026-05-27 14:53:15 +02:00
Fabien Potencier e3f66654b8 Fix deprecation notices in tests 2026-05-27 14:53:02 +02:00
Fabien Potencier 475fb690ac Guard sandbox __toString walker against self-referencing iterables 2026-05-27 14:53:02 +02:00
Fabien Potencier e9e818cbfc Fix sandbox __toString bypass via Stringable + Traversable containers 2026-05-27 14:53:01 +02:00
Fabien Potencier 8d6af0707b Fix sandbox __toString bypass via the in and not in operators 2026-05-27 14:52:32 +02:00
Fabien Potencier cc1e21a2a2 Fix sandbox __toString bypass via Traversable in join/replace filters 2026-05-27 14:52:30 +02:00
Fabien Potencier d9a6abc84f security #534 Fix sandbox bypass in the "column" filter under SourcePolicyInterface (fabpot)
This PR was squashed before being merged into the twig-3.x branch.

Discussion
----------

Fix sandbox bypass in the "column" filter under SourcePolicyInterface

Fixes #514

Commits
-------

afbaa2a9da Mark new SourcePolicyInterface column filter tests as `@group` legacy
09c6706407 Fix sandbox bypass in the "column" filter under SourcePolicyInterface
2026-05-27 14:50:29 +02:00
Fabien Potencier afbaa2a9da Mark new SourcePolicyInterface column filter tests as @group legacy
These tests pass a SourcePolicyInterface instance to SandboxExtension, which
triggers the 3.27 deprecation. Mark them legacy and assert the deprecation
to silence the PHPUnit "unhandled deprecation" report.
2026-05-27 14:49:53 +02:00
Fabien Potencier 09c6706407 Fix sandbox bypass in the "column" filter under SourcePolicyInterface 2026-05-27 14:49:52 +02:00
Fabien Potencier 3feda8a850 feature #4817 Add a strict mode to SecurityPolicy to opt-in to the 4.0 sandbox behavior for the extends/use tags and the parent/block/attribute functions (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Add a strict mode to SecurityPolicy to opt-in to the 4.0 sandbox behavior for the extends/use tags and the parent/block/attribute functions

#4813 follow-up

As `@stof` mentioned on Slack, there is currently no way to avoid the deprecation if you want to forbid those tags.

Commits
-------

af7bf5e181 Add a strict mode to SecurityPolicy to opt-in to the 4.0 sandbox behavior for the extends/use tags and the parent/block/attribute functions
2026-05-25 14:07:18 +02:00