From 8416f7ba519fa3bbd8c1ffc0000c1a7c5730efba Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 3 Nov 2015 08:24:46 +0100 Subject: [PATCH] [Yaml] deprecate unquoted indicator characters --- src/Symfony/Component/Yaml/Inline.php | 4 +-- src/Symfony/Component/Yaml/Parser.php | 14 ++++++++--- .../Yaml/Tests/Fixtures/sfQuotes.yml | 2 +- .../Component/Yaml/Tests/InlineTest.php | 15 +++++++++++ .../Component/Yaml/Tests/ParserTest.php | 25 +++++++++++++++++++ 5 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 6eb5ed53b3..65ee79e242 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -236,8 +236,8 @@ class Inline throw new ParseException(sprintf('Malformed inline YAML string (%s).', $scalar)); } - // a non-quoted string cannot start with @ or ` (reserved) - if ($output && ('@' === $output[0] || '`' === $output[0])) { + // a non-quoted string cannot start with @ or ` (reserved) nor with a scalar indicator (| or >) + if ($output && ('@' === $output[0] || '`' === $output[0] || '|' === $output[0] || '>' === $output[0])) { @trigger_error(sprintf('Not quoting a scalar starting with "%s" is deprecated since Symfony 2.8 and will throw a ParseException in 3.0.', $output[0]), E_USER_DEPRECATED); // to be thrown in 3.0 diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index a6c0f291c2..e595b404d4 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -114,7 +114,7 @@ class Parser $data[] = $parser->parse($block, $exceptionOnInvalidType, $objectSupport, $objectForMap); } else { - $data[] = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport, $objectForMap); + $data[] = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport, $objectForMap, $context); } } if ($isRef) { @@ -230,7 +230,7 @@ class Parser } } } else { - $value = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport, $objectForMap); + $value = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport, $objectForMap, $context); // Spec: Keys MUST be unique; first one wins. // But overwriting is allowed when a merge node is used in current block. if ($allowOverwrite || !isset($data[$key])) { @@ -445,12 +445,13 @@ class Parser * @param bool $exceptionOnInvalidType True if an exception must be thrown on invalid types false otherwise * @param bool $objectSupport True if object support is enabled, false otherwise * @param bool $objectForMap true if maps should return a stdClass instead of array() + * @param string $context The parser context (either sequence or mapping) * * @return mixed A PHP value * * @throws ParseException When reference does not exist */ - private function parseValue($value, $exceptionOnInvalidType, $objectSupport, $objectForMap) + private function parseValue($value, $exceptionOnInvalidType, $objectSupport, $objectForMap, $context) { if (0 === strpos($value, '*')) { if (false !== $pos = strpos($value, '#')) { @@ -472,6 +473,13 @@ class Parser return $this->parseBlockScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers)); } + if ('mapping' === $context && '"' !== $value[0] && "'" !== $value[0] && '[' !== $value[0] && '{' !== $value[0] && '!' !== $value[0] && false !== strpos($value, ': ')) { + @trigger_error(sprintf('Using a colon in an unquoted mapping value in line %d is deprecated since Symfony 2.8 and will throw a ParseException in 3.0.', $this->getRealCurrentLineNb() + 1), E_USER_DEPRECATED); + + // to be thrown in 3.0 + // throw new ParseException('A colon cannot be used in an unquoted mapping value.'); + } + try { return Inline::parse($value, $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs); } catch (ParseException $e) { diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/sfQuotes.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/sfQuotes.yml index 741f1befeb..7c60baec97 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/sfQuotes.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/sfQuotes.yml @@ -3,7 +3,7 @@ test: Some characters at the beginning of a string must be escaped brief: > Some characters at the beginning of a string must be escaped yaml: | - foo: | bar + foo: '| bar' php: | array('foo' => '| bar') --- diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index 0e1986d77f..67500727f7 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -205,6 +205,21 @@ class InlineTest extends \PHPUnit_Framework_TestCase return array(array('@'), array('`')); } + /** + * @group legacy + * @dataProvider getScalarIndicators + * throws \Symfony\Component\Yaml\Exception\ParseException in 3.0 + */ + public function testParseUnquotedScalarStartingWithScalarIndicator($indicator) + { + Inline::parse(sprintf('{ foo: %sfoo }', $indicator)); + } + + public function getScalarIndicators() + { + return array(array('|'), array('>')); + } + public function getTestsForParse() { return array( diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 19078220bb..e4c02d77b7 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -783,6 +783,31 @@ EOF; $this->assertEquals($expected, $this->parser->parse($yaml)); } + + /** + * @group legacy + * throw ParseException in Symfony 3.0 + */ + public function testColonInMappingValueException() + { + $yaml = <<parser->parse($yaml); + + $this->assertCount(1, $deprecations); + $this->assertContains('Using a colon in an unquoted mapping value in line 1 is deprecated since Symfony 2.8 and will throw a ParseException in 3.0.', $deprecations[0]); + + restore_error_handler(); + } } class B