Ensure filters/attributes aren't mistaken for operators

This commit is contained in:
brandonkelly
2026-02-23 08:57:49 -08:00
committed by Fabien Potencier
parent 206ad9f1a8
commit a9ac993938
2 changed files with 38 additions and 1 deletions
+1 -1
View File
@@ -544,7 +544,7 @@ class Lexer
// an operator that begins with a character must not have a dot or pipe before
if (ctype_alpha($expressionParser[0])) {
$r = '(?<![\.\|])'.$r;
$r = '(?<![\.\|]\s|.[\.\|])'.$r;
}
// an operator with a space can be any amount of whitespaces
+37
View File
@@ -420,6 +420,43 @@ class LexerTest extends TestCase
$this->addToAssertionCount(1);
}
public function testFilterAndAttributeNamedAfterOperator()
{
// Ensure that filters/attributes aren't mistaken for operators when their names conflict
// (see https://github.com/twigphp/Twig/issues/4767)
$template = '{{ \'foo\'|and }}'
.'{{ \'bar\' | and }}'
.'{{ foo.and }}'
.'{{ bar . and }}'
.'{{ foo and bar }}';
$lexer = new Lexer(new Environment(new ArrayLoader()));
$stream = $lexer->tokenize(new Source($template, 'index'));
foreach (['foo', 'bar'] as $value) {
$stream->expect(Token::VAR_START_TYPE);
$stream->expect(Token::STRING_TYPE, $value);
$stream->expect(Token::OPERATOR_TYPE, '|');
$stream->expect(Token::NAME_TYPE, 'and');
$stream->expect(Token::VAR_END_TYPE);
}
foreach (['foo', 'bar'] as $value) {
$stream->expect(Token::VAR_START_TYPE);
$stream->expect(Token::NAME_TYPE, $value);
$stream->expect(Token::OPERATOR_TYPE, '.');
$stream->expect(Token::NAME_TYPE, 'and');
$stream->expect(Token::VAR_END_TYPE);
}
$stream->expect(Token::VAR_START_TYPE);
$stream->expect(Token::NAME_TYPE, 'foo');
$stream->expect(Token::OPERATOR_TYPE, 'and');
$stream->expect(Token::NAME_TYPE, 'bar');
$stream->expect(Token::VAR_END_TYPE);
// add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
// can be executed without throwing any exceptions
$this->addToAssertionCount(1);
}
public function testUnterminatedVariable()
{
$template = '