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

Skip to content

DATABASE_URL gets corrupted when the container is compiled #36510

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
mnapoli opened this issue Apr 21, 2020 · 5 comments
Closed

DATABASE_URL gets corrupted when the container is compiled #36510

mnapoli opened this issue Apr 21, 2020 · 5 comments

Comments

@mnapoli
Copy link
Contributor

mnapoli commented Apr 21, 2020

Symfony version(s) affected: 4.4.* or 5.0.* -> I upgraded from 4.3 and this bug appeared.

Description
Given an environment variable like this:

DATABASE_URL=mysql://root:[email protected]:3306/mydb

The connection to the database fails. After investigation, I can see that the string gets transformed into the compiled container to something like this:

'mysql:/'.dirname(__DIR__,6).':[email protected]:3306/mydb'

I suspect this is somehow related to #12784 (which is 6 years old, so not directly related).

How to reproduce

What is interesting about this project

  • Have an environment variable like this:
DATABASE_URL=mysql://root:[email protected]:3306/mydb
  • Compile the container in a subdirectory of /root (or you could replace root with anything I guess)

The Kernel class has this addition that inlines the value of environment variables:

class Kernel extends BaseKernel
{
    ...
    protected function build(ContainerBuilder $container): void
    {
        if ('prod' === $this->environment) {
            $container->addCompilerPass(new ResolveEnvPlaceholdersPass(), PassConfig::TYPE_AFTER_REMOVING, -1000);
        }
    }
}

Possible Solution

Additional context

Doctrine config:

doctrine:
    dbal:
        driver: 'pdo_mysql'
        server_version: '5.7'
        charset: utf8mb4
        default_table_options:
            charset: utf8mb4
            collate: utf8mb4_unicode_ci
        # Initially this was `env(resolve:DATABASE_URL)`, I tried without resolve: but with the same result
        url: '%env(DATABASE_URL)%'
@nicolas-grekas
Copy link
Member

That's because of #34757. There is a combination of criteria that are required to hit this, which you listed. The extra compiler pass is the thing nobody does, which explains why this has not been reported before.

I don't know how to detect this situation. Any idea anyone?
Also, why this compiler pass?

@mnapoli
Copy link
Contributor Author

mnapoli commented Apr 21, 2020

Thanks for the quick response. I also managed to reproduce locally now.

The compiler pass was a requirement specific to this project, but I don't think it's important in the end.

You could have a similar value in any parameter (not environment variable) and get the same bug, is that correct?

I don't know how to detect this situation. Any idea anyone?

No idea at all for me.

@nicolas-grekas
Copy link
Member

Same issue leading to another corrupted argument: #37150

@addiks
Copy link
Contributor

addiks commented Jun 8, 2020

I have just written a reproduce-script for my other issues (#37150) but i guess it could also be used for this.
https://travis-ci.com/github/addiks/reproduce-script-for-symfony-issue-37150/builds/170334059
https://github.com/addiks/reproduce-script-for-symfony-issue-37150/blob/master/test.php

This issue also affects version 3.4.41.

My thoughts for a possible solution:

It appears that the PhpDumper class matches all arguments against a dynamic regex (stored in $this->targetDirRegex) like #/foo(/bar(/baz)?)?# (if the container was build in folder /foo/bar/baz). This regex will now also match other values that just coincidentally contain the string /foo, like mysql://foo@host.
To prevent this, the regex could be changed to only match if the value actually starts with the root-folder. If the pattern would be #^/foo(/bar(/baz)?)?#(notice the circumflex at the beginning), then only values beginning with /foo... would be matched and receive a replacement. False-positives could still occur if an argument begins with the root-dir when it is not intended as a directory-path, but the probability for a false-positive would be reduced greatly (i think). I am not sure if this could introduce other problems in some situations that i am not aware of right now.

The only other way to fix this (that comes to mind right now) would be to flag the services or arguments as "this is not a folder, do not change this!" explicitly. That would probably be a way safer method of dealing with this problem, but it has two downsides: a) The user has to know about this flag beforehand and b) It introduces some extra complexity in comparison with the other solution above.

I don't think that there is an absolute way of detecting this situation safely without the user explicitly choosing whether to replace or not for every instance, simply because symfony cannot know the intended use of a value beforehand.

@nicolas-grekas
Copy link
Member

Please check #37275

nicolas-grekas added a commit that referenced this issue Jun 18, 2020
…tives (nicolas-grekas)

This PR was merged into the 3.4 branch.

Discussion
----------

[DI] tighten detection of local dirs to prevent false positives

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #36510 and #37150
| License       | MIT
| Doc PR        | -

Commits
-------

b746dd9 [DI] tighten detection of local dirs to prevent false positives
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants