Skip to content

Commit 9b1eee1

Browse files
committed
bug #13896 [ExpressionLanguage] fixed issues when parsing postfix expressions (zerustech)
This PR was submitted for the 2.4 branch but it was merged into the 2.6 branch instead (closes #13896). Discussion ---------- [ExpressionLanguage] fixed issues when parsing postfix expressions Exception shall be thrown when parsing the following expressions: foo."#", foo."bar", foo.**, foo.123 The original parser didn't throw exception for foo."#", foo.** and foo.123 | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | n/a | License | MIT | Doc PR | n/a Commits ------- e504ebe [ExpressionLanguage] fixed issues when parsing postfix expressions
2 parents 051c3de + e504ebe commit 9b1eee1

File tree

2 files changed

+46
-5
lines changed

2 files changed

+46
-5
lines changed

src/Symfony/Component/ExpressionLanguage/Parser.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -314,12 +314,20 @@ public function parsePostfixExpression($node)
314314
if (
315315
$token->type !== Token::NAME_TYPE
316316
&&
317-
$token->type !== Token::NUMBER_TYPE
318-
&&
319-
// operators line "not" are valid method or property names
320-
($token->type !== Token::OPERATOR_TYPE && preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A', $token->value))
317+
// Operators like "not" and "matches" are valid method or property names,
318+
//
319+
// In other words, besides NAME_TYPE, OPERATOR_TYPE could also be parsed as a property or method.
320+
// This is because operators are processed by the lexer prior to names. So "not" in "foo.not()" or "matches" in "foo.matches" will be recognized as an operator first.
321+
// But in fact, "not" and "matches" in such expressions shall be parsed as method or property names.
322+
//
323+
// And this ONLY works if the operator consists of valid characters for a property or method name.
324+
//
325+
// Other types, such as STRING_TYPE and NUMBER_TYPE, can't be parsed as property nor method names.
326+
//
327+
// As a result, if $token is NOT an operator OR $token->value is NOT a valid property or method name, an exception shall be thrown.
328+
($token->type !== Token::OPERATOR_TYPE || !preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A', $token->value))
321329
) {
322-
throw new SyntaxError('Expected name or number', $token->cursor);
330+
throw new SyntaxError('Expected name', $token->cursor);
323331
}
324332

325333
$arg = new Node\ConstantNode($token->value);

src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,37 @@ private function createGetAttrNode($node, $item, $type)
161161
{
162162
return new Node\GetAttrNode($node, new Node\ConstantNode($item), new Node\ArgumentsNode(), $type);
163163
}
164+
165+
/**
166+
* @dataProvider getInvalidPostfixData
167+
* @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError
168+
*/
169+
public function testParseWithInvalidPostfixData($expr, $names = array())
170+
{
171+
$lexer = new Lexer();
172+
$parser = new Parser(array());
173+
$parser->parse($lexer->tokenize($expr), $names);
174+
}
175+
176+
public function getInvalidPostfixData()
177+
{
178+
return array(
179+
array(
180+
'foo."#"',
181+
array('foo'),
182+
),
183+
array(
184+
'foo."bar"',
185+
array('foo'),
186+
),
187+
array(
188+
'foo.**',
189+
array('foo'),
190+
),
191+
array(
192+
'foo.123',
193+
array('foo'),
194+
),
195+
);
196+
}
164197
}

0 commit comments

Comments
 (0)