584 Commits

Author SHA1 Message Date
Fabien Potencier 0d283d304a Throw a SyntaxError instead of a PHP fatal error when a macro argument is defined twice 2026-07-04 11:17:28 +02:00
Fabien Potencier 2f202b006b bug #4841 Fix Markup truthiness in boolean expressions (xtrime-ru)
This PR was merged into the 3.x branch.

Discussion
----------

Fix Markup truthiness in boolean expressions

## Summary

Fixes Markup truthiness handling in boolean expressions.

`trim` can return a `Twig\Markup` instance for safe strings. Empty `Markup` objects must behave like empty strings in Twig truth tests, but PHP treats all objects as truthy. This caused expressions like this to incorrectly evaluate as true:
```twig
{% set x %}    {% endset %}
{% if x|trim and x|trim %}fail{% else %}ok{% endif %}
```

This case was working properly in https://github.com/twigphp/Twig/releases/tag/v3.14.2 and earlier.

## Related commits
- Bug was introduced in [v3.15.0](https://github.com/twigphp/Twig/releases/tag/v3.15.0) in this commit https://github.com/twigphp/Twig/commit/10c3142d3b036910f63080070c101bfff61e0743
- Partially fixed here:  https://github.com/twigphp/Twig/commit/10c3142d3b036910f63080070c101bfff61e0743

## Changes

- Added `TrueTest::wrap()` to centralize wrapping non-primitive expressions with Twig’s Markup-aware true test.
- Reused `TrueTest::wrap()` in:
  - `IfNode`
  - conditional ternary expressions
  - `and`, `or`, and `xor` binary expressions
  - Elvis expressions
  - unary `not`
- Added regression coverage for boolean operators (`and`, `or`, `xor`, `not`) and ternary/Elvis expressions whose operands evaluate to empty `Markup`.

## Tests
```bash
./vendor/bin/simple-phpunit tests/IntegrationTest.php --filter markup_test
```

Commits
-------

f5afaabf54 Fix Markup truthiness in boolean expressions
2026-06-13 12:28:15 +02:00
Derrick Austin 153094b601 Fix a PHP 8.5 chr() deprecation when decoding octal string escapes
PHP 8.5 deprecates passing a value outside the [0, 255] range to chr().
The string-escape decoder in the lexer accepts up to three octal digits,
so an escape such as "\777" (= 511) reaches chr() out of range and emits:

    chr(): Providing a value not in-between 0 and 255 is deprecated ...

chr() already constrains the value with "% 256", so applying "% 256"
explicitly preserves the exact byte while silencing the deprecation. The
hex escape branch is unaffected because it is capped at two digits (0xff).
2026-06-13 07:22:26 +02:00
Alexander Pankratov f5afaabf54 Fix Markup truthiness in boolean expressions 2026-06-11 15:33:21 +02:00
Fabien Potencier c0504b90c5 Handle single-node child template bodies in cleanup 2026-06-11 07:44:00 +02:00
Fabien Potencier a69d3dc71e Keep captured block definitions supported 2026-06-11 07:43:59 +02:00
Fabien Potencier ffcae61b15 Move extends validation into correctness visitor 2026-06-11 07:43:47 +02:00
Fabien Potencier d96eac3895 Fix correctness visitor regressions 2026-06-11 07:43:46 +02:00
Fabien Potencier 89e8699a73 Fix test assertions that did not verify the intended behavior 2026-06-11 07:43:36 +02:00
Fabien Potencier 4b2e651dd5 Address review: fix block-nesting checks in CorrectnessNodeVisitor 2026-06-11 07:43:36 +02:00
Fabien Potencier de7bbc7be9 Move the extends-in-block and extends-in-macro errors into the CorrectnessNodeVisitor 2026-06-11 07:43:36 +02:00
Fabien Potencier c12100525e Introduce a CorrectnessNodeVisitor to validate that templates are semantically correct 2026-06-11 07:43:33 +02:00
Fabien Potencier 612dc96c18 feature #4838 Allow calling a macro with a dynamic name via the dot operator (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Allow calling a macro with a dynamic name via the dot operator

Closes #4715

Commits
-------

87093aab9e Allow calling a macro with a dynamic name via the dot operator
2026-06-07 09:36:06 +02:00
Fabien Potencier 87093aab9e Allow calling a macro with a dynamic name via the dot operator 2026-06-06 17:10:52 +02:00
Fabien Potencier aef7587fc8 feature #4819 Add an allow-list for tests to the sandbox security policy (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Add an allow-list for tests to the sandbox security policy

Commits
-------

416d07da1d Add an allow-list for tests to the sandbox security policy
2026-06-06 17:04:39 +02:00
Fabien Potencier 416d07da1d Add an allow-list for tests to the sandbox security policy 2026-06-06 11:08:56 +02:00
Fabien Potencier 0197736dfc Reduce memory usage of the context restoration compiled at the end of for loops 2026-06-06 09:31:56 +02:00
Fabien Potencier 29c4325afd Bump version to 3.28.0 for the always_allowed_in_sandbox feature 2026-06-06 08:56:59 +02:00
Fabien Potencier 1c53b790fb Add regression tests that always-allowed callables still enforce the sandbox __toString policy on arguments 2026-06-06 08:56:58 +02:00
Fabien Potencier 2d75c87d05 Add an always_allowed_in_sandbox flag for filters, functions, and tags 2026-06-06 08:56:58 +02:00
Fabien Potencier e3c0c3fe5a feature #4834 Track the source offset of each token and expose it in syntax errors (fabpot)
This PR was squashed before being merged into the 3.x branch.

Discussion
----------

Track the source offset of each token and expose it in syntax errors

Commits
-------

3868bac531 Avoid allocating a normalized copy when counting newlines without carriage returns
a82782ac30 Report columns in syntax errors
4943bb405c Track the source offset of each token
2026-06-06 08:56:09 +02:00
Fabien Potencier d0cc1fcd40 Remove issue references in tests 2026-06-06 08:55:16 +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 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 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
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 ee8ab447d7 Make IntegrationTestCase and NodeTestCase compatible with PHPUnit 11 2026-06-03 18:17:03 +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 8ec9530732 Fix inconsistent array access with a Stringable key 2026-05-29 10:06:57 +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 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 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 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 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 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 13:40:27 +02:00
Fabien Potencier cfaa2fd030 Deprecate the fact that the parent, block, and attribute functions are always allowed in a sandboxed template 2026-05-24 21:19:56 +02:00
Fabien Potencier 33690a4a28 Fix PHP 8.1+ implicit float-to-int deprecation in sandboxed array access 2026-05-24 17:39:37 +02:00