From 5af7d5321938ee1a17ceef4fef18dfc5bf9990b0 Mon Sep 17 00:00:00 2001 From: Jan Walther Date: Tue, 1 Aug 2023 16:37:55 +0200 Subject: [PATCH] [Process] Support finding executables independently of open_basedir --- src/Symfony/Component/Process/CHANGELOG.md | 1 + .../Component/Process/ExecutableFinder.php | 32 ++++++++----------- .../Component/Process/PhpExecutableFinder.php | 2 +- .../Process/Tests/ExecutableFinderTest.php | 24 ++++---------- 4 files changed, 21 insertions(+), 38 deletions(-) diff --git a/src/Symfony/Component/Process/CHANGELOG.md b/src/Symfony/Component/Process/CHANGELOG.md index 78241ab24d8e4..d6ec2032ce58f 100644 --- a/src/Symfony/Component/Process/CHANGELOG.md +++ b/src/Symfony/Component/Process/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG --- * Add `RunProcessMessage` and `RunProcessMessageHandler` + * Support using `Process::findExecutable()` independently of `open_basedir` 5.2.0 ----- diff --git a/src/Symfony/Component/Process/ExecutableFinder.php b/src/Symfony/Component/Process/ExecutableFinder.php index b31f7530bcecd..3681e3563e4e3 100644 --- a/src/Symfony/Component/Process/ExecutableFinder.php +++ b/src/Symfony/Component/Process/ExecutableFinder.php @@ -50,25 +50,10 @@ public function addSuffix(string $suffix) */ public function find(string $name, string $default = null, array $extraDirs = []): ?string { - if (\ini_get('open_basedir')) { - $searchPath = array_merge(explode(\PATH_SEPARATOR, \ini_get('open_basedir')), $extraDirs); - $dirs = []; - foreach ($searchPath as $path) { - // Silencing against https://bugs.php.net/69240 - if (@is_dir($path)) { - $dirs[] = $path; - } else { - if (basename($path) == $name && @is_executable($path)) { - return $path; - } - } - } - } else { - $dirs = array_merge( - explode(\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')), - $extraDirs - ); - } + $dirs = array_merge( + explode(\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')), + $extraDirs + ); $suffixes = ['']; if ('\\' === \DIRECTORY_SEPARATOR) { @@ -80,9 +65,18 @@ public function find(string $name, string $default = null, array $extraDirs = [] if (@is_file($file = $dir.\DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === \DIRECTORY_SEPARATOR || @is_executable($file))) { return $file; } + + if (!@is_dir($dir) && basename($dir) === $name.$suffix && @is_executable($dir)) { + return $dir; + } } } + $command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v'; + if (\function_exists('exec') && ($executablePath = strtok(@exec($command.' '.escapeshellarg($name)), \PHP_EOL)) && is_executable($executablePath)) { + return $executablePath; + } + return $default; } } diff --git a/src/Symfony/Component/Process/PhpExecutableFinder.php b/src/Symfony/Component/Process/PhpExecutableFinder.php index 09f15008e59e3..ae053641e93b0 100644 --- a/src/Symfony/Component/Process/PhpExecutableFinder.php +++ b/src/Symfony/Component/Process/PhpExecutableFinder.php @@ -34,7 +34,7 @@ public function find(bool $includeArgs = true): string|false if ($php = getenv('PHP_BINARY')) { if (!is_executable($php)) { $command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v'; - if ($php = strtok(exec($command.' '.escapeshellarg($php)), \PHP_EOL)) { + if (\function_exists('exec') && $php = strtok(exec($command.' '.escapeshellarg($php)), \PHP_EOL)) { if (!is_executable($php)) { return false; } diff --git a/src/Symfony/Component/Process/Tests/ExecutableFinderTest.php b/src/Symfony/Component/Process/Tests/ExecutableFinderTest.php index 155c5ee231ec9..54e740ec33e5d 100644 --- a/src/Symfony/Component/Process/Tests/ExecutableFinderTest.php +++ b/src/Symfony/Component/Process/Tests/ExecutableFinderTest.php @@ -19,20 +19,9 @@ */ class ExecutableFinderTest extends TestCase { - private string|false $path = false; - protected function tearDown(): void { - if ($this->path) { - // Restore path if it was changed. - putenv('PATH='.$this->path); - } - } - - private function setPath($path) - { - $this->path = getenv('PATH'); - putenv('PATH='.$path); + putenv('PATH='.($_SERVER['PATH'] ?? $_SERVER['Path'])); } public function testFind() @@ -41,7 +30,7 @@ public function testFind() $this->markTestSkipped('Cannot test when open_basedir is set'); } - $this->setPath(\dirname(\PHP_BINARY)); + putenv('PATH='.\dirname(\PHP_BINARY)); $finder = new ExecutableFinder(); $result = $finder->find($this->getPhpBinaryName()); @@ -57,7 +46,7 @@ public function testFindWithDefault() $expected = 'defaultValue'; - $this->setPath(''); + putenv('PATH='); $finder = new ExecutableFinder(); $result = $finder->find('foo', $expected); @@ -71,7 +60,7 @@ public function testFindWithNullAsDefault() $this->markTestSkipped('Cannot test when open_basedir is set'); } - $this->setPath(''); + putenv('PATH='); $finder = new ExecutableFinder(); @@ -86,7 +75,7 @@ public function testFindWithExtraDirs() $this->markTestSkipped('Cannot test when open_basedir is set'); } - $this->setPath(''); + putenv('PATH='); $extraDirs = [\dirname(\PHP_BINARY)]; @@ -129,7 +118,6 @@ public function testFindProcessInOpenBasedir() $this->markTestSkipped('Cannot run test on windows'); } - $this->setPath(''); $this->iniSet('open_basedir', \PHP_BINARY.\PATH_SEPARATOR.'/'); $finder = new ExecutableFinder(); @@ -154,7 +142,7 @@ public function testFindBatchExecutableOnWindows() $this->assertFalse(is_executable($target)); - $this->setPath(sys_get_temp_dir()); + putenv('PATH='.sys_get_temp_dir()); $finder = new ExecutableFinder(); $result = $finder->find(basename($target), false);