-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Yaml] Fail properly when the !php/const tag is used in a mapping k 8000 ey #35208
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -320,7 +320,11 @@ private static function dumpArray($value, $flags) | |
*/ | ||
public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i = 0, $evaluate = true, $references = [], $legacyOmittedKeySupport = false) | ||
{ | ||
if (\in_array($scalar[$i], ['"', "'"])) { | ||
if ('' === $scalar = (string) $scalar) { | ||
return ''; | ||
} | ||
|
||
if (isset($scalar[$i]) && \in_array($scalar[$i], ['"', "'"])) { | ||
// quoted scalar | ||
$output = self::parseQuotedScalar($scalar, $i); | ||
|
||
|
@@ -513,7 +517,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = [] | |
} | ||
|
||
if (!$isKeyQuoted) { | ||
$evaluatedKey = self::evaluateScalar($key, $flags, $references); | ||
$evaluatedKey = self::evaluateScalar($key, $flags, $references, true); | ||
|
||
if ('' !== $key && $evaluatedKey !== $key && !\is_string($evaluatedKey) && !\is_int($evaluatedKey)) { | ||
@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 = [] | |
* @param string $scalar | ||
* @param int $flags | ||
* @param array $references | ||
* @param bool $isMappingKey | ||
* | ||
* @return mixed The evaluated YAML string | ||
* | ||
* @throws ParseException when object parsing support was disabled and the parser detected a PHP object or when a reference could not be resolved | ||
*/ | ||
private static function evaluateScalar($scalar, $flags, $references = []) | ||
private static function evaluateScalar($scalar, $flags, $references = [], $isMappingKey = false) | ||
{ | ||
$scalar = trim($scalar); | ||
$scalarLower = strtolower($scalar); | ||
|
@@ -712,6 +717,10 @@ private static function evaluateScalar($scalar, $flags, $references = []) | |
return null; | ||
case 0 === strpos($scalar, '!php/const'): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The legacy tag does not need to be taken into account since they finish with ":", the mapping key is always the new tag. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this works with the legacy tag, this means to me that having an error during parsing when using the new tag is a bug and we should see how to fix that instead of changing the error message. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It doesn't work with the legacy tag. If you use the legacy tag as a key, eg |
||
if (self::$constantSupport) { | ||
if ($isMappingKey) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One edge case is if the constant '' is defined (define('', 'foo')). In this case it currently works but the resulting key value is the tag (!php/const), not the evaluated value. So I guess we don't care of breaking this case. |
||
throw new ParseException('The !php/const tag is not supported in a mapping key.', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); | ||
} | ||
|
||
$i = 0; | ||
if (\defined($const = self::parseScalar(substr($scalar, 11), 0, null, $i, false))) { | ||
return \constant($const); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This cast can be removed when merged in upper branches since the parameter is typed, so when false is passed it is converted to ''.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The docblock states that
$scalar
is a string. Can we detect the cases where we pass something else here and terminate there instead?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I did first was to cast to string before calling this method, to stay compliant with the method contract, but see #35208 (comment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we have to call the method at all if the scalar is not a string?