Commit Graph

590 Commits

Author SHA1 Message Date
Fabien Potencier 991294ae39 Drop the 3.x version from the SandboxExtension internal annotation 2026-09-25 23:52:43 +02:00
Fabien Potencier bb0dbfc229 Stop passing the template source to the sandbox checks that no longer use it 2026-09-25 23:52:13 +02:00
Fabien Potencier 07b8427e26 Merge branch '3.x' into 4.x 2026-09-25 18:04:23 +02:00
Fabien Potencier ddd9045b5c Skip the property checker call and memoize the class constant probe when reading an object attribute 2026-09-25 16:00:51 +02:00
Fabien Potencier 3417f483bf Fetch the escaper runtime once in the constructor of templates that escape 2026-09-25 12:44:56 +02:00
Fabien Potencier 00861d50ab Fix split trailing newline 2026-09-25 12:39:38 +02:00
Fabien Potencier f3bacf3877 Merge branch '3.x' into 4.x
* 3.x:
  Reuse the template wrapper of an already loaded template
  Stop the escaping safe analysis from retaining every analyzed node
  Allow to call TemplateWrapper::unwrap() without arguments
  Expose the escaping strategy a template was compiled with
  Improve macro call performance
  Fix IntlExtension inheriting values derived by ICU from a date formatter prototype
  Fix array access with a Stringable key on subclasses of ArrayObject and ArrayIterator
  Ignore the PHPUnit 10+ cache directory
  Cover and document the matches operator throwing on an invalid UTF-8 subject
  Report a clear error when a string cannot be split into characters
  Deprecate cloning a Twig environment
  Report the macro call parentheses deprecation once per call site and name the macro
  Bump version
  Prepare the 3.29.0 release
  Update CHANGELOG

# Conflicts:
#	.gitignore
#	CHANGELOG
#	doc/deprecated.rst
#	src/Environment.php
#	src/NodeVisitor/CorrectnessNodeVisitor.php
#	src/NodeVisitor/SafeAnalysisNodeVisitor.php
#	src/Template.php
#	tests/Fixtures/macros/call_without_parentheses.legacy.test
#	tests/ParserTest.php
#	tests/TemplateTest.php
#	tests/TwigMacroTest.php
2026-09-22 21:10:53 +01:00
Fabien Potencier d722e8af93 bug #4931 Fix array access with a Stringable key on subclasses of ArrayObject and ArrayIterator (fabpot)
This PR was squashed before being merged into the 3.x branch.

Discussion
----------

Fix array access with a Stringable key on subclasses of ArrayObject and ArrayIterator

Commits
-------

4aae99e92c Fix array access with a Stringable key on subclasses of ArrayObject and ArrayIterator
2026-09-20 20:17:49 +01:00
Fabien Potencier 4aae99e92c Fix array access with a Stringable key on subclasses of ArrayObject and ArrayIterator 2026-09-20 20:17:42 +01:00
Fabien Potencier 5c1be030c5 Report a clear error when a string cannot be split into characters 2026-09-18 17:15:50 +01:00
Fabien Potencier cabb305b5a Fix merge conflict resolution 2026-08-29 08:27:21 +02:00
Fabien Potencier f640320202 Merge branch '3.x' into 4.x
* 3.x: (26 commits)
  Remove the documentation comments compilation overhead
  Clarify source function trust requirements
  Throw on PCRE errors in the matches operator
  Document that reusing a non-rewindable iterator after destructuring is unsupported
  Release destructuring temporaries after assignment
  Deprecate prefixed macro definedness checks
  Fix duplicate macro deprecation wording
  Throw when list formatting fails
  Document that sequence destructuring consumes one value per pattern slot
  Fix the html_attr documentation about iterables in data attributes
  Warn about untrusted input with the default Tempest markdown converter
  Document that overriding MacroNode::compile() is not supported anymore
  Merge overlapping CHANGELOG entries for the destructuring fatal error fix
  Document that include_only keeps global variables available
  Remove lazy macro import resolution
  Honor date formatter prototype calendars
  Fix Stringable keys for ArrayAccess implementations
  Fix repeated object destructuring evaluation
  Restore void return type compatibility for extension points
  Reject destructuring patterns containing no variables
  ...

# Conflicts:
#	CHANGELOG
#	doc/deprecated.rst
#	doc/filters/format_datetime.rst
#	extra/twig-extra-bundle/DependencyInjection/Compiler/MissingExtensionSuggestorPass.php
#	extra/twig-extra-bundle/DependencyInjection/TwigExtraExtension.php
#	extra/twig-extra-bundle/TwigExtraBundle.php
#	src/MacroNamespace.php
#	src/Node/MacrosNode.php
#	src/Parser.php
#	src/Test/IntegrationTestCase.php
#	src/Test/NodeTestCase.php
#	tests/CallMacroTest.php
#	tests/ExpressionParserTest.php
#	tests/Fixtures/macros/duplicate_definition.legacy.test
#	tests/Node/MacrosTest.php
#	tests/ParserTest.php
2026-08-29 00:25:20 +02:00
Fabien Potencier c32656815b minor #4908 Remove the documentation comments compilation overhead (fabpot)
This PR was squashed before being merged into the 3.x branch.

Discussion
----------

Remove the documentation comments compilation overhead

Documentation comments are now attached to semantic nodes during parsing, removing the dedicated AST traversal. Token parsers returning placeholder nodes can select the semantic documentation target.

Commits
-------

60eed4ccd5 Remove the documentation comments compilation overhead
2026-08-29 00:19:33 +02:00
Fabien Potencier 60eed4ccd5 Remove the documentation comments compilation overhead 2026-08-29 00:19:29 +02:00
Fabien Potencier e5347301d7 Throw on PCRE errors in the matches operator 2026-08-28 08:41:42 +02:00
Fabien Potencier 3265884e93 bug #4899 Fix Stringable keys for ArrayAccess implementations (fabpot)
This PR was squashed before being merged into the 3.x branch.

Discussion
----------

Fix Stringable keys for ArrayAccess implementations

This restores support for `Stringable` keys on string-keyed `ArrayAccess` implementations such as `ArrayObject` and `ArrayIterator`, while preserving object keys for `SplObjectStorage`.

The object key is attempted first and is converted to a string only when the implementation rejects it. The optimized and strict lookup paths now share the same behavior without duplicate existence checks.

Commits
-------

f3f1649955 Fix Stringable keys for ArrayAccess implementations
2026-08-27 08:42:51 +02:00
Fabien Potencier f3f1649955 Fix Stringable keys for ArrayAccess implementations 2026-08-27 08:42:47 +02:00
Fabien Potencier 6bbbb49c3e Restore void return type compatibility for extension points 2026-08-27 07:27:31 +02:00
Fabien Potencier e2014eb92a Fix Traversable sequence destructuring semantics 2026-08-23 09:40:21 +02:00
Fabien Potencier d7fc3d6dc9 Merge branch '3.x' into 4.x
* 3.x:
  Attach documentation comments to nodes

# Conflicts:
#	CHANGELOG
#	src/Lexer.php
#	src/Node/Node.php
#	src/Parser.php
#	src/Token.php
2026-08-19 16:44:35 +02:00
Fabien Potencier 6806e30474 Attach documentation comments to nodes 2026-08-19 16:41:17 +02:00
Fabien Potencier 60d3b3452a Merge branch '3.x' into 4.x
* 3.x:
  Add support for tempest/markdown in markdown-extra
  Add the include_only function to render a template without access to the current context
  Clarify duplicate macro deprecation message
  Deduplicate template error handling

# Conflicts:
#	.gitignore
#	CHANGELOG
#	extra/markdown-extra/composer.json
#	src/Extension/CoreExtension.php
#	src/Parser.php
#	src/Template.php
#	tests/Fixtures/macros/duplicate_definition.legacy.test
2026-08-16 10:57:50 +02:00
Fabien Potencier dc8f96df3e Add the include_only function to render a template without access to the current context 2026-08-11 20:58:31 +02:00
Fabien Potencier ce013c063e Remove deprecated code 2026-07-30 14:14:10 +02:00
Fabien Potencier 986a765019 Merge branch '3.x' into 4.x
* 3.x:
  Redesign macro calls and argument handling

# Conflicts:
#	CHANGELOG
#	doc/deprecated.rst
#	src/ExpressionParser/Infix/ArgumentsTrait.php
#	src/ExpressionParser/Infix/DotExpressionParser.php
#	src/ExpressionParser/Infix/FunctionExpressionParser.php
#	src/Extension/CoreExtension.php
#	src/Node/Expression/MacroReferenceExpression.php
#	src/Node/Expression/MethodCallExpression.php
#	src/Node/Expression/TempNameExpression.php
#	src/Node/MacroNode.php
#	src/Node/ModuleNode.php
#	src/Template.php
#	tests/Fixtures/macros/call_without_parentheses.legacy.test
#	tests/Node/Expression/MacroReferenceTest.php
#	tests/Node/MacroTest.php
2026-07-30 14:02:30 +02:00
Fabien Potencier d7f8b4eb1c Redesign macro calls and argument handling 2026-07-30 13:53:24 +02:00
Fabien Potencier b34f022583 Remove deprecated code 2026-07-30 13:52:37 +02:00
Fabien Potencier 3197df7b5e Merge branch '3.x' into 4.x
* 3.x:
  Make the sandbox a first-class citizen with a dedicated Sandbox class

# Conflicts:
#	CHANGELOG
#	doc/deprecated.rst
#	doc/tags/sandbox.rst
#	phpstan-baseline.neon
#	src/Extension/CoreExtension.php
#	src/Extension/SandboxExtension.php
#	src/Sandbox/SecurityPolicy.php
2026-07-30 13:04:50 +02:00
Fabien Potencier b762bc94b9 Make the sandbox a first-class citizen with a dedicated Sandbox class 2026-07-30 12:05:47 +02:00
Fabien Potencier 0b6e824ea8 Merge branch '3.x' into 4.x
* 3.x:
  Add void return type hint even in tests
  Run php-cs-fixer sequentially so the void_return src-only customiser is applied
  Fix CHANGELOG
  [Intl] Add format_list filter using PHP 8.5's IntlListFormatter

# Conflicts:
#	.github/workflows/ci.yml
#	CHANGELOG
#	extra/cssinliner-extra/Tests/LegacyFunctionsTest.php
#	extra/html-extra/Tests/CvaTest.php
#	extra/html-extra/Tests/HtmlAttrMergeTest.php
#	extra/html-extra/Tests/HtmlAttrTest.php
#	extra/html-extra/Tests/LegacyFunctionsTest.php
#	extra/inky-extra/Tests/LegacyFunctionsTest.php
#	extra/markdown-extra/Tests/FunctionalTest.php
#	extra/markdown-extra/Tests/LegacyFunctionsTest.php
#	extra/twig-extra-bundle/DependencyInjection/Compiler/MissingExtensionSuggestorPass.php
#	extra/twig-extra-bundle/DependencyInjection/TwigExtraExtension.php
#	extra/twig-extra-bundle/TwigExtraBundle.php
#	src/Extension/CoreExtension.php
#	src/Extension/EscaperExtension.php
#	src/Node/CheckSecurityCallNode.php
#	src/Node/Expression/FunctionExpression.php
#	src/Node/ModuleNode.php
#	src/Node/Node.php
#	src/Node/TypesNode.php
#	src/Resources/core.php
#	src/Resources/debug.php
#	src/Test/IntegrationTestCase.php
#	tests/CustomExtensionTest.php
#	tests/EnvironmentTest.php
#	tests/ExpressionParserTest.php
#	tests/Extension/CoreTest.php
#	tests/Extension/EscaperTest.php
#	tests/Extension/LegacyDebugFunctionsTest.php
#	tests/Extension/LegacyStringLoaderFunctionsTest.php
#	tests/Extension/SandboxStateChangeTest.php
#	tests/Extension/SandboxTest.php
#	tests/LexerTest.php
#	tests/Node/Expression/CallTest.php
#	tests/Node/Expression/ConditionalTest.php
#	tests/Node/NodeTest.php
#	tests/Resources/LegacyCoreTest.php
#	tests/TemplateTest.php
#	tests/Util/CallableArgumentsExtractorTest.php
2026-07-12 13:55:37 +02:00
Fabien Potencier 9c6d76b61c Add void return type hint even in tests 2026-07-12 13:43:08 +02:00
Fabien Potencier eb8ca3b887 Remove deprecated code 2026-06-11 08:16:23 +02:00
Fabien Potencier 04ace9dba0 Merge branch '3.x' into 4.x
* 3.x:
  Handle single-node child template bodies in cleanup
  Keep captured block definitions supported
  Clarify captured block deprecation wording
  Simplify correctness visitor checks
  Move extends validation into correctness visitor
  Fix correctness visitor regressions
  Fix test assertions that did not verify the intended behavior
  Address review: fix block-nesting checks in CorrectnessNodeVisitor
  Move the extends-in-block and extends-in-macro errors into the CorrectnessNodeVisitor
  Introduce a CorrectnessNodeVisitor to validate that templates are semantically correct
  Mark Markup as final
  Allow calling a macro with a dynamic name via the dot operator
  Add an allow-list for tests to the sandbox security policy
  Fix markdown_to_html mangling content that starts with a blank line

# Conflicts:
#	CHANGELOG
#	doc/deprecated.rst
#	doc/sandbox.rst
#	src/ExpressionParser/Infix/DotExpressionParser.php
#	src/Extension/CoreExtension.php
#	src/Markup.php
#	src/Node/CheckSecurityNode.php
#	src/Node/Expression/Filter/DefaultFilter.php
#	src/Node/Expression/NullCoalesceExpression.php
#	src/Node/IfNode.php
#	src/NodeVisitor/SandboxNodeVisitor.php
#	src/Parser.php
#	src/Sandbox/SecurityPolicy.php
#	tests/Extension/SandboxTest.php
#	tests/ParserTest.php
2026-06-11 07:57:54 +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 b1cac7c3ab Enforce the sandbox Markup exception for every security policy 2026-06-09 21:46:52 +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 82bc07bc64 Merge branch '3.x' into 4.x
* 3.x:
  Reduce memory usage of the context restoration compiled at the end of for loops
  Clarify sandbox always-allowed trust boundary
  Bump version to 3.28.0 for the always_allowed_in_sandbox feature
  Add regression tests that always-allowed callables still enforce the sandbox __toString policy on arguments
  Document the criteria for always-allowed sandbox items and list 4.0 built-ins
  Add an always_allowed_in_sandbox flag for filters, functions, and tags
  Remove issue references in tests
  Avoid allocating a normalized copy when counting newlines without carriage returns
  Report columns in syntax errors
  Track the source offset of each token

# Conflicts:
#	CHANGELOG
#	doc/deprecated.rst
#	doc/sandbox.rst
#	src/Environment.php
#	src/Error/Error.php
#	src/Lexer.php
#	src/Node/ForNode.php
#	src/Token.php
#	src/TwigCallableInterface.php
#	tests/Extension/SandboxTest.php
#	tests/Node/ForTest.php
2026-06-06 11:03:40 +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 16a7e4ec0d Merge branch '3.x' into 4.x
* 3.x:
  Document how to customize the markdown_to_html converter
  Make the include() function return a Markup object
  Fix nested block() resolution when a directly rendered block calls parent()
  Fix nested block() resolution when a directly rendered block calls parent()
  Document storing an enum in a variable to avoid repeating its FQCN
  Stop reporting a skipped test in IntegrationTestCase when there is no legacy test to run
  Document {#--#} as the replacement for the deprecated spaceless filter
  Skip the string cast in PrintNode when the expression is already a string and add tests
  Ensure PrintNode is yielding string content
  CoreExtension::getAttribute: small improvement regarding getter/isser/hasser

# Conflicts:
#	CHANGELOG
#	tests/Node/ForTest.php
2026-06-06 08:48:52 +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 a3eda4b1fd Make the include() function return a Markup object 2026-06-04 21:32:12 +02:00
Fabien Potencier 4c359db061 Remove stale SourcePolicyInterface reference from the column filter comment 2026-06-02 14:12:01 +02:00
Fabien Potencier 19099de78e Merge branch '3.x' into 4.x
* 3.x:
  Skip the sandbox `__toString` check on arguments whose PHP parameter type cannot implicitly coerce to string
  Fix  CS
  Bump version
  Prepare the 3.27.1 release
  Fix inconsistent array access with a Stringable key
  Preserve IteratorAggregate identity in sandbox __toString walker
  Fix tests
  Bump version
  Prepare the 3.27.0 release
  Fix sandbox filter/tag/function allow-list bypass when sandbox state changes between renders
  Document new support for any expression as a dynamic mapping key
  Fix sandbox __toString policy bypass via dynamic mapping keys
  Fix deprecation notices in tests
  Guard sandbox `__toString` walker against self-referencing iterables
  Fix sandbox `__toString` bypass via `Stringable` + `Traversable` containers
  Fix sandbox `__toString` bypass via the `in` and `not in` operators
  Fix sandbox __toString bypass via Traversable in join/replace filters
  Mark new SourcePolicyInterface column filter tests as @group legacy
  Fix sandbox bypass in the "column" filter under SourcePolicyInterface
  Fix sandbox bypass in deprecated internal wrappers

# Conflicts:
#	CHANGELOG
#	src/Environment.php
#	src/Node/Expression/ArrayExpression.php
#	src/Node/Expression/CallExpression.php
#	src/Resources/core.php
#	src/Template.php
#	src/Util/CallableArgumentsExtractor.php
#	src/Util/ReflectionCallable.php
#	tests/Extension/SandboxTest.php
#	tests/Resources/LegacyCoreTest.php
#	tests/TemplateTest.php
2026-06-02 14:05:57 +02:00
Fabien Potencier d25f98f45b Preserve IteratorAggregate identity in sandbox __toString walker 2026-05-29 09:31:03 +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 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 cc1e21a2a2 Fix sandbox __toString bypass via Traversable in join/replace filters 2026-05-27 14:52:30 +02:00
Fabien Potencier 09c6706407 Fix sandbox bypass in the "column" filter under SourcePolicyInterface 2026-05-27 14:49:52 +02:00
Fabien Potencier 39e843bd1e Merge branch '3.x' into 4.x
* 3.x:
  Document transitive behavior of allowed sandbox operations
  Remove obsolete PHP 8.0 workaround for Closure::__invoke attribute access
2026-05-25 08:40:02 +02:00