Skip to content

Commit de6715b

Browse files
committed
[Yaml] Fail properly when the !php/const tag is used in a mapping key
1 parent 8e9aafc commit de6715b

File tree

2 files changed

+40
-6
lines changed

2 files changed

+40
-6
lines changed

src/Symfony/Component/Yaml/Inline.php

+15-6
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,10 @@ private static function dumpArray($value, $flags)
320320
*/
321321
public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i = 0, $evaluate = true, $references = [], $legacyOmittedKeySupport = false)
322322
{
323+
if ('' === $scalar) {
324+
return '';
325+
}
326+
323327
if (\in_array($scalar[$i], ['"', "'"])) {
324328
// quoted scalar
325329
$output = self::parseQuotedScalar($scalar, $i);
@@ -513,7 +517,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = []
513517
}
514518

515519
if (!$isKeyQuoted) {
516-
$evaluatedKey = self::evaluateScalar($key, $flags, $references);
520+
$evaluatedKey = self::evaluateScalar($key, $flags, $references, true);
517521

518522
if ('' !== $key && $evaluatedKey !== $key && !\is_string($evaluatedKey) && !\is_int($evaluatedKey)) {
519523
@trigger_error(self::getDeprecationMessage('Implicit casting of incompatible mapping keys to strings is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.'), E_USER_DEPRECATED);
@@ -611,12 +615,13 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = []
611615
* @param string $scalar
612616
* @param int $flags
613617
* @param array $references
618+
* @param bool $isMappingKey
614619
*
615620
* @return mixed The evaluated YAML string
616621
*
617622
* @throws ParseException when object parsing support was disabled and the parser detected a PHP object or when a reference could not be resolved
618623
*/
619-
private static function evaluateScalar($scalar, $flags, $references = [])
624+
private static function evaluateScalar($scalar, $flags, $references = [], $isMappingKey = false)
620625
{
621626
$scalar = trim($scalar);
622627
$scalarLower = strtolower($scalar);
@@ -660,7 +665,7 @@ private static function evaluateScalar($scalar, $flags, $references = [])
660665
case 0 === strpos($scalar, '! '):
661666
@trigger_error(self::getDeprecationMessage('Using the non-specific tag "!" is deprecated since Symfony 3.4 as its behavior will change in 4.0. It will force non-evaluating your values in 4.0. Use plain integers or !!float instead.'), E_USER_DEPRECATED);
662667

663-
return (int) self::parseScalar(substr($scalar, 2), $flags);
668+
return (int) self::parseScalar((string) substr($scalar, 2), $flags);
664669
case 0 === strpos($scalar, '!php/object:'):
665670
if (self::$objectSupport) {
666671
@trigger_error(self::getDeprecationMessage('The !php/object: tag to indicate dumped PHP objects is deprecated since Symfony 3.4 and will be removed in 4.0. Use the !php/object (without the colon) tag instead.'), E_USER_DEPRECATED);
@@ -687,7 +692,7 @@ private static function evaluateScalar($scalar, $flags, $references = [])
687692
return null;
688693
case 0 === strpos($scalar, '!php/object'):
689694
if (self::$objectSupport) {
690-
return unserialize(self::parseScalar(substr($scalar, 12)));
695+
return unserialize(self::parseScalar((string) substr($scalar, 12)));
691696
}
692697

693698
if (self::$exceptionOnInvalidType) {
@@ -712,8 +717,12 @@ private static function evaluateScalar($scalar, $flags, $references = [])
712717
return null;
713718
case 0 === strpos($scalar, '!php/const'):
714719
if (self::$constantSupport) {
720+
if ($isMappingKey) {
721+
throw new ParseException('The !php/const tag is not supported in a mapping key.', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
722+
}
723+
715724
$i = 0;
716-
if (\defined($const = self::parseScalar(substr($scalar, 11), 0, null, $i, false))) {
725+
if (\defined($const = self::parseScalar((string) substr($scalar, 11), 0, null, $i, false))) {
717726
return \constant($const);
718727
}
719728

@@ -833,7 +842,7 @@ private static function parseTag($value, &$i, $flags)
833842
*/
834843
public static function evaluateBinaryScalar($scalar)
835844
{
836-
$parsedBinaryData = self::parseScalar(preg_replace('/\s/', '', $scalar));
845+
$parsedBinaryData = self::parseScalar(preg_replace('/\s/', '', $scalar) ?: '');
837846

838847
if (0 !== (\strlen($parsedBinaryData) % 4)) {
839848
throw new ParseException(sprintf('The normalized base64 encoded data (data without whitespace characters) length must be a multiple of four (%d bytes given).', \strlen($parsedBinaryData)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);

src/Symfony/Component/Yaml/Tests/InlineTest.php

+25
Original file line numberDiff line numberDiff line change
@@ -797,4 +797,29 @@ public function getTestsForOctalNumbers()
797797
'negative octal number' => [-28, '-034'],
798798
];
799799
}
800+
801+
public function testParseScalarDoesNotFailWithAnEmptyString()
802+
{
803+
$this->assertSame('', Inline::parseScalar(''));
804+
}
805+
806+
/**
807+
* @dataProvider phpConstTagInAMappingKeyThrowsProvider
808+
*/
809+
public function testPhpConstTagInAMappingKeyThrows($extra)
810+
{
811+
$this->expectException(ParseException::class);
812+
$this->expectExceptionMessage('The !php/const tag is not supported in a mapping key at line 1 (near "!php/const").');
813+
814+
Inline::parse(sprintf('{!php/const%s: foo}', $extra), Yaml::PARSE_CONSTANT);
815+
}
816+
817+
public function phpConstTagInAMappingKeyThrowsProvider()
818+
{
819+
return [
820+
[''],
821+
[' '],
822+
[' MyConst'],
823+
];
824+
}
800825
}

0 commit comments

Comments
 (0)