Skip to content

Commit 1a71ac4

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

File tree

2 files changed

+41
-7
lines changed

2 files changed

+41
-7
lines changed

src/Symfony/Component/Yaml/Inline.php

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,11 @@ 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 (\in_array($scalar[$i], ['"', "'"])) {
323+
if ('' === $scalar) {
324+
return '';
325+
}
326+
327+
if (isset($scalar[$i]) && \in_array($scalar[$i], ['"', "'"])) {
324328
// quoted scalar
325329
$output = self::parseQuotedScalar($scalar, $i);
326330

@@ -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

Lines changed: 25 additions & 0 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy