From cb362f284f9d556f23f1e7d869735d080efb4ca1 Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Thu, 4 Aug 2016 13:37:15 +0100 Subject: [PATCH] Add Yaml::PARSE_EXCEPTION_ON_DUPLICATE to throw exceptions on duplicates --- UPGRADE-3.2.md | 6 ++ UPGRADE-4.0.md | 3 + src/Symfony/Component/Yaml/CHANGELOG.md | 3 + src/Symfony/Component/Yaml/Inline.php | 6 ++ src/Symfony/Component/Yaml/Parser.php | 6 ++ .../Fixtures/YtsSpecificationExamples.yml | 1 + .../Yaml/Tests/Fixtures/sfMergeKey.yml | 5 -- .../Component/Yaml/Tests/ParserTest.php | 74 +++++++++++++++++++ 8 files changed, 99 insertions(+), 5 deletions(-) diff --git a/UPGRADE-3.2.md b/UPGRADE-3.2.md index edd6d70cb5..2c88a54c46 100644 --- a/UPGRADE-3.2.md +++ b/UPGRADE-3.2.md @@ -70,3 +70,9 @@ Validator // ... } ``` + +Yaml +---- + + * Support for silently ignoring duplicate keys in YAML has been deprecated and + will lead to a `ParseException` in Symfony 4.0. diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 2abe339922..655587ba64 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -230,6 +230,9 @@ Yaml * The `!!php/object` tag to indicate dumped PHP objects was removed in favor of the `!php/object` tag. + * Duplicate keys in YAML leads to a `ParseException`. + + Validator --------- diff --git a/src/Symfony/Component/Yaml/CHANGELOG.md b/src/Symfony/Component/Yaml/CHANGELOG.md index 7a14fb2467..abc26ec140 100644 --- a/src/Symfony/Component/Yaml/CHANGELOG.md +++ b/src/Symfony/Component/Yaml/CHANGELOG.md @@ -10,6 +10,9 @@ CHANGELOG Yaml::parse('!php/const:PHP_INT_MAX', Yaml::PARSE_CONSTANT); ``` + * Support for silently ignoring duplicate keys in YAML has been deprecated and + will lead to a `ParseException` in Symfony 4.0. + 3.1.0 ----- diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 326699442e..7b3a4c612c 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -475,6 +475,8 @@ class Inline // are processed sequentially. if (!isset($output[$key])) { $output[$key] = $value; + } else { + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); } $done = true; break; @@ -486,6 +488,8 @@ class Inline // are processed sequentially. if (!isset($output[$key])) { $output[$key] = $value; + } else { + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); } $done = true; break; @@ -499,6 +503,8 @@ class Inline // are processed sequentially. if (!isset($output[$key])) { $output[$key] = $value; + } else { + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); } $done = true; --$i; diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 5cf5a88824..6bd56073f6 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -241,6 +241,8 @@ class Parser // But overwriting is allowed when a merge node is used in current block. if ($allowOverwrite || !isset($data[$key])) { $data[$key] = null; + } else { + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); } } else { $value = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(), $flags); @@ -248,6 +250,8 @@ class Parser // But overwriting is allowed when a merge node is used in current block. if ($allowOverwrite || !isset($data[$key])) { $data[$key] = $value; + } else { + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); } } } else { @@ -256,6 +260,8 @@ class Parser // But overwriting is allowed when a merge node is used in current block. if ($allowOverwrite || !isset($data[$key])) { $data[$key] = $value; + } else { + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); } } if ($isRef) { diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml index 268c02efeb..ac0c69da0a 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml @@ -1574,6 +1574,7 @@ php: | array( 'fixed' => 1230.15, ) +--- test: Float yaml: | canonical: 1.23015e+3 diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml index 4b67d34100..8d2b4d3818 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml @@ -18,11 +18,7 @@ yaml: | x: Oren c: foo: bar - foo: ignore bar: foo - duplicate: - foo: bar - foo: ignore foo2: &foo2 a: Ballmer ding: &dong [ fi, fei, fo, fam] @@ -48,7 +44,6 @@ php: | array( 'foo' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian'), 'bar' => array('a' => 'before', 'd' => 'other', 'b' => 'new', 'c' => array('foo' => 'bar', 'bar' => 'foo'), 'x' => 'Oren'), - 'duplicate' => array('foo' => 'bar'), 'foo2' => array('a' => 'Ballmer'), 'ding' => array('fi', 'fei', 'fo', 'fam'), 'check' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam', 'isit' => 'tested'), diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index a2711fc789..d8c0718142 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Yaml\Tests; +use Symfony\Bridge\PhpUnit\ErrorAssert; use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Parser; @@ -770,6 +771,7 @@ EOF * * @see http://yaml.org/spec/1.2/spec.html#id2759572 * @see http://yaml.org/spec/1.1/#id932806 + * @group legacy */ public function testMappingDuplicateKeyBlock() { @@ -789,6 +791,9 @@ EOD; $this->assertSame($expected, Yaml::parse($input)); } + /** + * @group legacy + */ public function testMappingDuplicateKeyFlow() { $input = <<assertSame($expected, Yaml::parse($input)); } + /** + * @dataProvider getParseExceptionOnDuplicateData + * @requires function Symfony\Bridge\PhpUnit\ErrorAssert::assertDeprecationsAreTriggered + * throws \Symfony\Component\Yaml\Exception\ParseException in 4.0 + */ + public function testParseExceptionOnDuplicate($input, $duplicate_key) + { + ErrorAssert::assertDeprecationsAreTriggered(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $duplicate_key), function () use ($input) { + Yaml::parse($input); + }); + } + + public function getParseExceptionOnDuplicateData() + { + $tests = array(); + + $yaml = <<