Skip to content

Commit 0773b18

Browse files
fancywebnicolas-grekas
authored andcommitted
[DependencyInjection] Fix autocasting null env values to empty string with container.env_var_processors_locator
1 parent 69e1127 commit 0773b18

File tree

2 files changed

+58
-30
lines changed

2 files changed

+58
-30
lines changed

src/Symfony/Component/DependencyInjection/Container.php

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -369,43 +369,42 @@ protected function load(string $file)
369369
*/
370370
protected function getEnv(string $name)
371371
{
372-
if (isset($this->resolving[$envName = "env($name)"])) {
373-
throw new ParameterCircularReferenceException(array_keys($this->resolving));
374-
}
375-
if (isset($this->envCache[$name]) || \array_key_exists($name, $this->envCache)) {
376-
return $this->envCache[$name];
377-
}
378372
if (!$this->has($id = 'container.env_var_processors_locator')) {
379373
$this->set($id, new ServiceLocator([]));
380374
}
381-
if (!$this->getEnv) {
382-
$this->getEnv = \Closure::fromCallable([$this, 'getEnv']);
383-
}
384-
$processors = $this->get($id);
385-
386-
if (false !== $i = strpos($name, ':')) {
387-
$prefix = substr($name, 0, $i);
388-
$localName = substr($name, 1 + $i);
389-
} else {
390-
$prefix = 'string';
391-
$localName = $name;
392-
}
375+
$this->getEnv ?? $this->getEnv = function ($name, $recursive = true) use ($id) {
376+
if (isset($this->resolving[$envName = "env($name)"])) {
377+
throw new ParameterCircularReferenceException(array_keys($this->resolving));
378+
}
379+
if (\array_key_exists($name, $this->envCache)) {
380+
return $this->envCache[$name];
381+
}
382+
383+
$processors = $this->get($id);
384+
385+
if (false !== $i = strpos($name, ':')) {
386+
$prefix = substr($name, 0, $i);
387+
$localName = substr($name, 1 + $i);
388+
} else {
389+
$prefix = 'string';
390+
$localName = $name;
391+
}
392+
393+
$processor = $processors->has($prefix) ? $processors->get($prefix) : new EnvVarProcessor($this);
393394

394-
if ($processors->has($prefix)) {
395-
$processor = $processors->get($prefix);
396-
} else {
397-
$processor = new EnvVarProcessor($this);
398-
if (false === $i) {
395+
if (false === $i && !$recursive) {
399396
$prefix = '';
400397
}
401-
}
402398

403-
$this->resolving[$envName] = true;
404-
try {
405-
return $this->envCache[$name] = $processor->getEnv($prefix, $localName, $this->getEnv);
406-
} finally {
407-
unset($this->resolving[$envName]);
408-
}
399+
$this->resolving[$envName] = true;
400+
try {
401+
return $this->envCache[$name] = $processor->getEnv($prefix, $localName, $this->getEnv);
402+
} finally {
403+
unset($this->resolving[$envName]);
404+
}
405+
};
406+
407+
return ($this->getEnv)($name, false);
409408
}
410409

411410
/**

src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\DependencyInjection\Container;
1616
use Symfony\Component\DependencyInjection\ContainerInterface;
17+
use Symfony\Component\DependencyInjection\EnvVarProcessor;
1718
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
1819
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
1920
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
2021
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
2122
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
23+
use Symfony\Component\DependencyInjection\ServiceLocator;
2224
use Symfony\Contracts\Service\ResetInterface;
2325

2426
class ContainerTest extends TestCase
@@ -405,6 +407,33 @@ public function testRequestAnInternalSharedPrivateService()
405407
$c->get('internal_dependency');
406408
$c->get('internal');
407409
}
410+
411+
public function testGetEnvDoesNotAutoCastNullWithDefaultEnvVarProcessor()
412+
{
413+
$container = new Container();
414+
$container->setParameter('env(FOO)', null);
415+
$container->compile();
416+
417+
$r = new \ReflectionMethod($container, 'getEnv');
418+
$r->setAccessible(true);
419+
$this->assertNull($r->invoke($container, 'FOO'));
420+
}
421+
422+
public function testGetEnvDoesNotAutoCastNullWithEnvVarProcessorsLocatorReturningDefaultEnvVarProcessor()
423+
{
424+
$container = new Container();
425+
$container->setParameter('env(FOO)', null);
426+
$container->set('container.env_var_processors_locator', new ServiceLocator([
427+
'string' => static function () use ($container): EnvVarProcessor {
428+
return new EnvVarProcessor($container);
429+
},
430+
]));
431+
$container->compile();
432+
433+
$r = new \ReflectionMethod($container, 'getEnv');
434+
$r->setAccessible(true);
435+
$this->assertNull($r->invoke($container, 'FOO'));
436+
}
408437
}
409438

410439
class ProjectServiceContainer extends Container

0 commit comments

Comments
 (0)