Skip to content

Commit

Permalink
bug #23949 [Dotenv] Get env using $_SERVER to work with fastcgi_param…
Browse files Browse the repository at this point in the history
… and workaround thread safety issues (nicolas-grekas)

This PR was merged into the 3.3 branch.

Discussion
----------

[Dotenv] Get env using $_SERVER to work with fastcgi_param and workaround thread safety issues

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

`getenv()` is not thread safe, and doesn't work with `fastcgi_param`, see links in linked issue.

Commits
-------

f76e420 [Dotenv] Get env using $_SERVER to work with fastcgi_param and workaround thread safety issues
  • Loading branch information
fabpot committed Aug 22, 2017
2 parents 2204f91 + f76e420 commit 420f089
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 5 deletions.
4 changes: 2 additions & 2 deletions src/Symfony/Component/DependencyInjection/Container.php
Expand Up @@ -438,13 +438,13 @@ protected function getEnv($name)
if (isset($this->envCache[$name]) || array_key_exists($name, $this->envCache)) {
return $this->envCache[$name];
}
if (0 !== strpos($name, 'HTTP_') && isset($_SERVER[$name])) {
if (isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')) {
return $this->envCache[$name] = $_SERVER[$name];
}
if (isset($_ENV[$name])) {
return $this->envCache[$name] = $_ENV[$name];
}
if (false !== $env = getenv($name)) {
if (false !== ($env = getenv($name)) && null !== $env) { // null is a possible value because of thread safety issues
return $this->envCache[$name] = $env;
}
if (!$this->hasParameter("env($name)")) {
Expand Down
18 changes: 15 additions & 3 deletions src/Symfony/Component/Dotenv/Dotenv.php
Expand Up @@ -70,13 +70,17 @@ public function populate($values)
unset($loadedVars['']);

foreach ($values as $name => $value) {
if (!isset($loadedVars[$name]) && (isset($_ENV[$name]) || isset($_SERVER[$name]) || false !== getenv($name))) {
$notHttpName = 0 !== strpos($name, 'HTTP_');
// don't check existence with getenv() because of thread safety issues
if (!isset($loadedVars[$name]) && (isset($_ENV[$name]) || (isset($_SERVER[$name]) && $notHttpName))) {
continue;
}

putenv("$name=$value");
$_ENV[$name] = $value;
$_SERVER[$name] = $value;
if ($notHttpName) {
$_SERVER[$name] = $value;
}

$loadedVars[$name] = true;
}
Expand Down Expand Up @@ -363,7 +367,15 @@ private function resolveVariables($value)
}

$name = $matches[3];
$value = isset($this->values[$name]) ? $this->values[$name] : (isset($_ENV[$name]) ? $_ENV[$name] : (string) getenv($name));
if (isset($this->values[$name])) {
$value = $this->values[$name];
} elseif (isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')) {
$value = $_SERVER[$name];
} elseif (isset($_ENV[$name])) {
$value = $_ENV[$name];
} else {
$value = (string) getenv($name);
}

if (!$matches[2] && isset($matches[4])) {
$value .= '}';
Expand Down
13 changes: 13 additions & 0 deletions src/Symfony/Component/Dotenv/Tests/DotenvTest.php
Expand Up @@ -208,13 +208,26 @@ public function testServerSuperglobalIsNotOverriden()
public function testEnvVarIsNotOverriden()
{
putenv('TEST_ENV_VAR=original_value');
$_SERVER['TEST_ENV_VAR'] = 'original_value';

$dotenv = new DotEnv();
$dotenv->populate(array('TEST_ENV_VAR' => 'new_value'));

$this->assertSame('original_value', getenv('TEST_ENV_VAR'));
}

public function testHttpVarIsPartiallyOverriden()
{
$_SERVER['HTTP_TEST_ENV_VAR'] = 'http_value';

$dotenv = new DotEnv();
$dotenv->populate(array('HTTP_TEST_ENV_VAR' => 'env_value'));

$this->assertSame('env_value', getenv('HTTP_TEST_ENV_VAR'));
$this->assertSame('env_value', $_ENV['HTTP_TEST_ENV_VAR']);
$this->assertSame('http_value', $_SERVER['HTTP_TEST_ENV_VAR']);
}

public function testMemorizingLoadedVarsNamesInSpecialVar()
{
// Special variable not exists
Expand Down

0 comments on commit 420f089

Please sign in to comment.