From 440e0b7b638072cb68581c7786bf8db3d4e36702 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 4 Dec 2019 12:12:45 +0100 Subject: [PATCH] support YAML 1.2 octal notation, deprecate YAML 1.1 one --- UPGRADE-5.1.md | 16 +++++++++++ UPGRADE-6.0.md | 16 +++++++++++ src/Symfony/Component/Yaml/CHANGELOG.md | 16 +++++++++++ src/Symfony/Component/Yaml/Inline.php | 16 +++++++++++ .../Fixtures/YtsSpecificationExamples.yml | 4 +-- .../Component/Yaml/Tests/Fixtures/sfTests.yml | 7 ----- .../Component/Yaml/Tests/InlineTest.php | 27 ++++++++++++++++--- 7 files changed, 90 insertions(+), 12 deletions(-) diff --git a/UPGRADE-5.1.md b/UPGRADE-5.1.md index cbb014851e..fb6625014e 100644 --- a/UPGRADE-5.1.md +++ b/UPGRADE-5.1.md @@ -164,4 +164,20 @@ Security Yaml ---- + * Added support for parsing numbers prefixed with `0o` as octal numbers. + * Deprecated support for parsing numbers starting with `0` as octal numbers. They will be parsed as strings as of Symfony 6.0. Prefix numbers with `0o` + so that they are parsed as octal numbers. + + Before: + + ```yaml + Yaml::parse('072'); + ``` + + After: + + ```yaml + Yaml::parse('0o72'); + ``` + * Deprecated using the `!php/object` and `!php/const` tags without a value. diff --git a/UPGRADE-6.0.md b/UPGRADE-6.0.md index 67d4557d7a..6acccd599e 100644 --- a/UPGRADE-6.0.md +++ b/UPGRADE-6.0.md @@ -111,4 +111,20 @@ Security Yaml ---- + * Added support for parsing numbers prefixed with `0o` as octal numbers. + * Removed support for parsing numbers starting with `0` as octal numbers. They will be parsed as strings. Prefix numbers with `0o` + so that they are parsed as octal numbers. + + Before: + + ```yaml + Yaml::parse('072'); + ``` + + After: + + ```yaml + Yaml::parse('0o72'); + ``` + * Removed support for using the `!php/object` and `!php/const` tags without a value. diff --git a/src/Symfony/Component/Yaml/CHANGELOG.md b/src/Symfony/Component/Yaml/CHANGELOG.md index 6993288240..d4f2b5d781 100644 --- a/src/Symfony/Component/Yaml/CHANGELOG.md +++ b/src/Symfony/Component/Yaml/CHANGELOG.md @@ -4,6 +4,22 @@ CHANGELOG 5.1.0 ----- + * Added support for parsing numbers prefixed with `0o` as octal numbers. + * Deprecated support for parsing numbers starting with `0` as octal numbers. They will be parsed as strings as of Symfony 6.0. Prefix numbers with `0o` + so that they are parsed as octal numbers. + + Before: + + ```yaml + Yaml::parse('072'); + ``` + + After: + + ```yaml + Yaml::parse('0o72'); + ``` + * Added `yaml-lint` binary. * Deprecated using the `!php/object` and `!php/const` tags without a value. diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 52c2763e3f..68e0093a1b 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -631,6 +631,14 @@ class Inline default: throw new ParseException(sprintf('The string "%s" could not be parsed as it uses an unsupported built-in tag.', $scalar), self::$parsedLineNumber, $scalar, self::$parsedFilename); } + case preg_match('/^(?:\+|-)?0o(?P[0-7_]++)$/', $scalar, $matches): + $value = str_replace('_', '', $matches['value']); + + if ('-' === $scalar[0]) { + return -octdec($value); + } else { + return octdec($value); + } // Optimize for returning strings. // no break @@ -644,11 +652,19 @@ class Inline $raw = $scalar; $cast = (int) $scalar; + if ('0' === $scalar[0] && '0' !== $scalar) { + trigger_deprecation('symfony/yaml', '5.1', 'Support for parsing numbers prefixed with 0 as octal numbers. They will be parsed as strings as of 6.0.'); + } + return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw); case '-' === $scalar[0] && ctype_digit(substr($scalar, 1)): $raw = $scalar; $cast = (int) $scalar; + if ('0' === $scalar[1] && '-0' !== $scalar) { + trigger_deprecation('symfony/yaml', '5.1', 'Support for parsing numbers prefixed with 0 as octal numbers. They will be parsed as strings as of 6.0.'); + } + return '0' == $scalar[1] ? -octdec(substr($scalar, 1)) : (($raw === (string) $cast) ? $cast : $raw); case is_numeric($scalar): case Parser::preg_match(self::getHexRegex(), $scalar): diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml index 80696cd1e6..b5f41a2b1e 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml @@ -509,7 +509,7 @@ test: Integers spec: 2.19 yaml: | canonical: 12345 - octal: 014 + octal: 0o14 hexadecimal: 0xC php: | [ @@ -1501,7 +1501,7 @@ ruby: | test: Integer yaml: | canonical: 12345 - octal: 014 + octal: 0o14 hexadecimal: 0xC php: | [ diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/sfTests.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/sfTests.yml index 2ea417a728..4588e922cf 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/sfTests.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/sfTests.yml @@ -96,13 +96,6 @@ yaml: | php: | ['foo', ['bar' => ['bar' => 'foo']]] --- -test: Octal -brief: as in spec example 2.19, octal value is converted -yaml: | - foo: 0123 -php: | - ['foo' => 83] ---- test: Octal strings brief: Octal notation in a string must remain a string yaml: | diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index bbae6cf3ff..71623436de 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -299,8 +299,8 @@ class InlineTest extends TestCase ['123.45_67', 123.4567], ['0x4D2', 0x4D2], ['0x_4_D_2_', 0x4D2], - ['02333', 02333], - ['0_2_3_3_3', 02333], + ['0o2333', 02333], + ['0o_2_3_3_3', 02333], ['.Inf', -log(0)], ['-.Inf', log(0)], ["'686e444'", '686e444'], @@ -379,7 +379,7 @@ class InlineTest extends TestCase ["'quoted string'", 'quoted string'], ['12.30e+02', 12.30e+02], ['0x4D2', 0x4D2], - ['02333', 02333], + ['0o2333', 02333], ['.Inf', -log(0)], ['-.Inf', log(0)], ["'686e444'", '686e444'], @@ -734,9 +734,30 @@ class InlineTest extends TestCase } public function getTestsForOctalNumbers() + { + return [ + 'positive octal number' => [28, '0o34'], + 'positive octal number with sign' => [28, '+0o34'], + 'negative octal number' => [-28, '-0o34'], + ]; + } + + /** + * @group legacy + * @dataProvider getTestsForOctalNumbersYaml11Notation + */ + public function testParseOctalNumbersYaml11Notation(int $expected, string $yaml) + { + $this->expectDeprecation('Since symfony/yaml 5.1: Support for parsing numbers prefixed with 0 as octal numbers. They will be parsed as strings as of 6.0.'); + + self::assertSame($expected, Inline::parse($yaml)); + } + + public function getTestsForOctalNumbersYaml11Notation() { return [ 'positive octal number' => [28, '034'], + 'positive octal number with separator' => [1243, '0_2_3_3_3'], 'negative octal number' => [-28, '-034'], ]; }