Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[DI] Allow binary values in parameters. #25928

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

Conversation

bburnichon
Copy link
Contributor

Q A
Branch? master
Bug fix? yes
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #25916
License MIT
Doc PR none yet

This adds binary type in container xsd definition file

@xabbuh
Copy link
Member

xabbuh commented Jan 25, 2018

Doesn't this apply to 2.7 too?

@@ -1775,7 +1775,12 @@ private function export($value)

private function doExport($value, $resolveEnv = false)
{
if (is_string($value) && false !== strpos($value, "\n")) {
if (is_string($value) && preg_match('/[\x00-\x08\x0b-\x1f\x7f-\xff]+/', $value,$matches)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, otherwise, PhpDumper generates invalid UTF-8 files. As I was unable to properly add safely required characters

@@ -298,6 +298,10 @@ private function convertParameters(array $parameters, $type, \DOMElement $parent
$element->setAttribute('type', 'expression');
$text = $this->document->createTextNode(self::phpToXml((string) $value));
$element->appendChild($text);
} elseif (is_string($value) && preg_match('/[\x00-\x08\x0b-\x1f\x7f-\xff]/', $value)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about !preg_match('//u', $value) 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.

I tried /\p{C}/u but it was not working as expected

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I retested it and tried to detect control characters instead except whitespaces

@@ -511,6 +511,12 @@ private function getArgumentsAsPhp(\DOMElement $node, $name, $file, $lowercase =
}
$arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'));
break;
case 'binary':
if (!preg_match('#^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$#', $arg->nodeValue)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that necessary? base64_decode() would return false anyway which we could check for to detect errors, can't we?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, could be done this way also. I generally tend to avoid calling methods with invalid parameters.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would side with @xabbuh here: This class should not care about how a valid base64 string looks like. This is an implementation detail of the base64_decode function.

@bburnichon bburnichon force-pushed the container-with-non-utf8-parameters branch from c43ca2c to e5d9ba8 Compare January 25, 2018 14:00
@bburnichon
Copy link
Contributor Author

bburnichon commented Jan 25, 2018

I've done this PR against master only as it requires xsd to have a new binary definition. But the actual fix can be applied to all versions I think.

fabbot.io gives an error in a fixture file. Could this be avoided?

@@ -511,6 +511,12 @@ private function getArgumentsAsPhp(\DOMElement $node, $name, $file, $lowercase =
}
$arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'));
break;
case 'binary':
if (!preg_match('#^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$#', $arg->nodeValue)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would side with @xabbuh here: This class should not care about how a valid base64 string looks like. This is an implementation detail of the base64_decode function.

@derrabus
Copy link
Member

fabbot.io gives an error in a fixture file. Could this be avoided?

You did not cause the error, so you can ignore it, imho.

@xabbuh xabbuh added this to the 2.7 milestone Jan 26, 2018
@dunglas
Copy link
Member

dunglas commented Jan 26, 2018

It deserves a unit test.

I would be more comfortable to merge this change in master instead of in 2.7. It's not that trivial.

@bburnichon
Copy link
Contributor Author

I made PR against master, not 2.7. Also, what kind of unit test need to be added? I already added the use case in Dumpers and Loaders. Do you have another type of parameter to check?

@bburnichon
Copy link
Contributor Author

ping @derrabus @dunglas @xabbuh Can you change target to master instead of 2.7 I do agree that this is a new feature that should go to next version of php. On older version, a bug warning should indicate binary parameters are not well handled.

@nicolas-grekas nicolas-grekas modified the milestones: 2.7, 4.1 Feb 27, 2018
@nicolas-grekas nicolas-grekas changed the title Allow binary values in parameters. [DI] Allow binary values in parameters. Feb 27, 2018
@xabbuh
Copy link
Member

xabbuh commented Mar 4, 2018

The CS complaints in the fixtures file can indeed be ignored. But can you please switch back to using explicit array() instead of the short array notation in the dumper class? :)

@@ -511,6 +511,12 @@ private function getArgumentsAsPhp(\DOMElement $node, $name, $file, $lowercase =
}
$arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'));
break;
case 'binary':
if (false === $value = base64_decode($arg->nodeValue)) {
throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="binary" is not valid base64 encoded string', $name));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[...] is not a valid [...]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also terminate the exception message with a dot.

@@ -1775,7 +1775,12 @@ private function export($value)

private function doExport($value, $resolveEnv = false)
{
if (is_string($value) && false !== strpos($value, "\n")) {
if (is_string($value) && \in_array(preg_match('/[^\s\P{Cc}]/u', $value), [false, 1], true)) {
Copy link
Member

@xabbuh xabbuh Mar 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the change for the PHP dumper really necessary? Was there anything breaking without this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really but then generated file could contain non-utf8 characters and opening generated file with an ide leads to warnings about file encoding.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nothing we need to worry about IMO

@@ -298,6 +298,10 @@ private function convertParameters(array $parameters, $type, \DOMElement $parent
$element->setAttribute('type', 'expression');
$text = $this->document->createTextNode(self::phpToXml((string) $value));
$element->appendChild($text);
} elseif (is_string($value) && \in_array(preg_match('/[^\s\P{Cc}]/u', $value), [false, 1], true)) {
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 need to check for both false and 1? Do we cover both values with the current test suite?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

false is returned when value contains non-utf8 characters. 1 is returned when a control character is present in string. You're right a case is missing in current test suite.

@bburnichon
Copy link
Contributor Author

Used traditional array syntax and added test on parameter with a single control char.

@bburnichon bburnichon force-pushed the container-with-non-utf8-parameters branch from af66815 to ae1684c Compare March 5, 2018 09:14
@@ -511,6 +511,12 @@ private function getArgumentsAsPhp(\DOMElement $node, $name, $file, $lowercase =
}
$arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'));
break;
case 'binary':
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It this really legitimate? I mean: if !!binary is a core yaml feature, it should be transparent. Yaml tagged-values are only for custom tags, not core ones AFAIK.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked for a way to indicate in a XML file (which should be a valid UTF-8 file) that a value was base64_encoded(). I though this was the exact same purpose as in yaml file. I did not knew that !!binary was part of the yaml specification.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO using the same term here is legitimate. I would keep it as is.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, sorry, I misread the code, all good here

@@ -1811,7 +1811,12 @@ private function export($value)

private function doExport($value, $resolveEnv = false)
{
if (is_string($value) && false !== strpos($value, "\n")) {
if (is_string($value) && \in_array(preg_match('/[^\s\P{Cc}]/u', $value), array(false, 1), true)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When can preg_match return false here?
What's the reasoning for choosing this regexp? (any reference/inspiration maybe?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If $value is not an UTF-8 character string, preg_match will return false because of the u modifier.
Regexp was chosen to detects all characters which are control characters \p{Cc} and not a space (which are valid ascii). I mean, putting a bell character in a string is very unlikely done in purpose. I don't know of a way to put this in a file except by copy/paste.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hum, I see. Then why unicode at all? No need for the u modifier, isn't it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I not set u modifier, I can NOT use \p{Cc} to find the allowed characters as its extension for unicode. My first try was just selecting all characters outside standard ASCII but it would filter too much IMO.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for unicode, let's list the ASCII Cc explicitly, here they are:
https://en.wikipedia.org/wiki/Unicode_control_characters

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want a different regex for XML and PHP serialization? I mean, in XML, I need to check whether string contains only valid UTF-8 characters implying check with the u modifier.
For PHP, I can only check for [\0-\x1f\x7f] but then simple strings like "Foo\tTab" would be base64 encoded whereas "\xf0" would not.

Copy link
Member

@nicolas-grekas nicolas-grekas Mar 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest only one way to detect binary, and using this:
[\x00-\x08\x0B\x0E-\x1A\x1C-\x1F\x7F]

@@ -1811,7 +1811,12 @@ private function export($value)

private function doExport($value, $resolveEnv = false)
{
if (is_string($value) && false !== strpos($value, "\n")) {
if (is_string($value) && \in_array(preg_match('/[\x00-\x08\x0B\x0E-\x1A\x1C-\x1F\x7F]/u', $value), array(false, 1), true)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for the u modifier, thus no need for in_array

@nicolas-grekas
Copy link
Member

as bugfix on 3.4?

@fabpot
Copy link
Member

fabpot commented Mar 27, 2018

Thank you @bburnichon.

@fabpot fabpot closed this Mar 27, 2018
fabpot added a commit that referenced this pull request Mar 27, 2018
This PR was squashed before being merged into the 4.1-dev branch (closes #25928).

Discussion
----------

[DI] Allow binary values in parameters.

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | yes
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #25916
| License        | MIT
| Doc PR        | none yet

This adds `binary` type in container xsd definition file

Commits
-------

cb23134 [DI] Allow binary values in parameters.
@stof
Copy link
Member

stof commented Mar 27, 2018

XML Dumper changes are missing their tests

@bburnichon bburnichon deleted the container-with-non-utf8-parameters branch March 27, 2018 14:06
@stof
Copy link
Member

stof commented Mar 27, 2018

We should also support it for argument types for consistency

@@ -298,6 +298,10 @@ private function convertParameters(array $parameters, $type, \DOMElement $parent
$element->setAttribute('type', 'expression');
$text = $this->document->createTextNode(self::phpToXml((string) $value));
$element->appendChild($text);
} elseif (\is_string($value) && !preg_match('/^[^\x00-\x08\x0B\x0E-\x1A\x1C-\x1F\x7F]*+$/u', $value)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need the u modifier here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, to ensure string is a valid UTF8 string for XML file.

@fabpot fabpot mentioned this pull request May 7, 2018
fabpot added a commit that referenced this pull request Jun 28, 2020
This PR was merged into the 4.4 branch.

Discussion
----------

[DI] fix parsing of argument type=binary in xml

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | yes
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tickets       |
| License       | MIT
| Doc PR        |

Parameters and arguments can be of type="binary" since #25928. But the XSD forgot to be updated for arguments.
So if you try to run `bin/console debug:container` you'd get an error like

```
In XmlFileLoader.php line 385:

  Unable to parse file "var/cache/dev/App_KernelDevDebugContainer.xml": [ERROR 1840] Element '{ht
  tp://symfony.com/schema/dic/services}argument', attribute 'type': [facet 'enumeration'] The value 'binary' is not a
  n element of the set {'abstract', 'collection', 'service', 'expression', 'string', 'constant', 'iterator', 'service
  _locator', 'tagged', 'tagged_iterator', 'tagged_locator'}. (in /home/benny/project/ - line 505, column 0)
  [ERROR 1824] Element '{http://symfony.com/schema/dic/services}argument', attribute 'type': 'binary' is not a valid
  value of the atomic type '{http://symfony.com/schema/dic/services}argument_type'. (in /home/benny/project/ - line 5
  05, column 0)`
```

Commits
-------

70b6a00 [DI] fix parsing of argument type=binary in xml
nicolas-grekas added a commit that referenced this pull request Mar 10, 2023
…ers. (vtsykun)

This PR was merged into the 5.4 branch.

Discussion
----------

[DependencyInjection] Fix support binary values in parameters.

| Q             | A
| ------------- | ---
| Branch?       | 5.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #49638
| License       | MIT
| Doc PR        | -

This issue related to #25928

### Step to reproduce

1. Add parameter like this
```yaml
parameters:
    banner_message: "\e[37;44m#StandWith\e[30;43mUkraine\e[0m"
```

2. Run command `debug:router`

Actual result:

![Selection_1343](https://user-images.githubusercontent.com/21358010/224194622-6d814bbc-823d-43db-8e11-43a46f09ad57.png)

Commits
-------

8541643 Fix support binary values in parameters.
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.

8 participants