Skip to content

[Yaml] Fail properly when the !php/const tag is used in a mapping key #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

Closed
wants to merge 1 commit into from

Conversation

fancyweb
Copy link
Contributor

@fancyweb fancyweb commented Jan 4, 2020

Q A
Branch? 3.4
Bug fix? no
New feature? no
Deprecations? no
Tickets #35179 (comment)
License MIT
Doc PR -

This PR improves the DX of the linked issue case + fixes the parseScalar method + fixes some cases that call it with non string values.

@@ -712,8 +717,12 @@ private static function evaluateScalar($scalar, $flags, $references = [])
return null;
case 0 === strpos($scalar, '!php/const'):
Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.

Copy link
Member

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 !php/const:MY_CONST: "value", then the parsed key is !php/const (the new one) because : is the key / value separator. So it's impossible to be a in a $isMappingKey case and in a legacy tag that ends with :.

@@ -712,8 +717,12 @@ private static function evaluateScalar($scalar, $flags, $references = [])
return null;
case 0 === strpos($scalar, '!php/const'):
if (self::$constantSupport) {
if ($isMappingKey) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.

@nicolas-grekas nicolas-grekas added this to the 3.4 milestone Jan 4, 2020
@fancyweb
Copy link
Contributor Author

fancyweb commented Jan 4, 2020

Other tags also have major problems, the key is never evaluated, but in the end they "work", ie they don't end up in a exception. That's why I changed only this one since it already end up in a exception anyway. But I think we should completely fix all those behaviors, but on master (with deprecations). It's difficult on 3.4 with all the legacy tags.

@fancyweb fancyweb force-pushed the yaml-tag-in-mapping-key branch from 1a71ac4 to e4254fe Compare January 4, 2020 13:23
@@ -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) {
Copy link
Contributor Author

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 ''.

Copy link
Member

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?

Copy link
Contributor Author

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).

Copy link
Member

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?

@@ -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) {
Copy link
Member

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?

@@ -712,8 +717,12 @@ private static function evaluateScalar($scalar, $flags, $references = [])
return null;
case 0 === strpos($scalar, '!php/const'):
Copy link
Member

Choose a reason for hiding this comment

The 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.

@xabbuh
Copy link
Member

xabbuh commented Jan 13, 2020

I had a deeper look at this and I think not parsing the constants in YAML keys is a bug of the parser when parsing the inline notation. Using the expanded syntax constants are parsed properly (we actually did a bugfix for that in the past too, see #22878). So I would actually fix the parser instead (see #35318 for it).

@xabbuh
Copy link
Member

xabbuh commented Jan 14, 2020

#35318 has been merged

@fancyweb fancyweb deleted the yaml-tag-in-mapping-key branch January 14, 2020 07:31
nicolas-grekas added a commit that referenced this pull request Feb 3, 2020
… const tag (fancyweb)

This PR was merged into the 3.4 branch.

Discussion
----------

[Yaml][Inline] Fail properly on empty object tag and empty const tag

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | -
| License       | MIT
| Doc PR        | -

Rework of #35208 to not end up in `parseScalar` with an empty string or a boolean (and thus, avoid unfriendly error such as `Trying to access array offset on value of type bool`).

Ping @xabbuh

Commits
-------

bdf02c0 [Yaml][Inline] Fail properly on empty object tag and empty const tag
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants