mirror of
https://github.com/symfony/process.git
synced 2026-03-23 23:42:06 +01:00
[Process] On Windows, don't rely on the OS to find executables
This commit is contained in:
@@ -85,6 +85,7 @@ class Process implements \IteratorAggregate
|
||||
private ?int $cachedExitCode = null;
|
||||
|
||||
private static ?bool $sigchild = null;
|
||||
private static array $executables = [];
|
||||
|
||||
/**
|
||||
* Exit codes translation table.
|
||||
@@ -1543,6 +1544,12 @@ class Process implements \IteratorAggregate
|
||||
return $commandline;
|
||||
}
|
||||
|
||||
if ('\\' === \DIRECTORY_SEPARATOR && isset($commandline[0][0]) && \strlen($commandline[0]) === strcspn($commandline[0], ':/\\')) {
|
||||
// On Windows, we don't rely on the OS to find the executable if possible to avoid lookups
|
||||
// in the current directory which could be untrusted. Instead we use the ExecutableFinder.
|
||||
$commandline[0] = (self::$executables[$commandline[0]] ??= (new ExecutableFinder())->find($commandline[0])) ?? $commandline[0];
|
||||
}
|
||||
|
||||
return implode(' ', array_map($this->escapeArgument(...), $commandline));
|
||||
}
|
||||
|
||||
|
||||
@@ -80,8 +80,8 @@ class ProcessFailedExceptionTest extends TestCase
|
||||
|
||||
$exception = new ProcessFailedException($process);
|
||||
|
||||
$this->assertEquals(
|
||||
"The command \"$cmd\" failed.\n\nExit Code: $exitCode($exitText)\n\nWorking directory: {$workingDirectory}\n\nOutput:\n================\n{$output}\n\nError Output:\n================\n{$errorOutput}",
|
||||
$this->assertStringMatchesFormat(
|
||||
"The command \"%s\" failed.\n\nExit Code: $exitCode($exitText)\n\nWorking directory: {$workingDirectory}\n\nOutput:\n================\n{$output}\n\nError Output:\n================\n{$errorOutput}",
|
||||
str_replace("'php'", 'php', $exception->getMessage())
|
||||
);
|
||||
}
|
||||
@@ -126,9 +126,9 @@ class ProcessFailedExceptionTest extends TestCase
|
||||
|
||||
$exception = new ProcessFailedException($process);
|
||||
|
||||
$this->assertEquals(
|
||||
"The command \"$cmd\" failed.\n\nExit Code: $exitCode($exitText)\n\nWorking directory: {$workingDirectory}",
|
||||
str_replace("'php'", 'php', $exception->getMessage())
|
||||
$this->assertStringMatchesFormat(
|
||||
"The command \"%s\" failed.\n\nExit Code: $exitCode($exitText)\n\nWorking directory: {$workingDirectory}",
|
||||
$exception->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1687,6 +1687,17 @@ class ProcessTest extends TestCase
|
||||
$this->assertSame(\SIGTERM, $process->getTermSignal());
|
||||
}
|
||||
|
||||
public function testPathResolutionOnWindows()
|
||||
{
|
||||
if ('\\' !== \DIRECTORY_SEPARATOR) {
|
||||
$this->markTestSkipped('This test is for Windows platform only');
|
||||
}
|
||||
|
||||
$process = $this->getProcess(['where']);
|
||||
|
||||
$this->assertSame('C:\\Windows\\system32\\where.EXE', $process->getCommandLine());
|
||||
}
|
||||
|
||||
private function getProcess(string|array $commandline, ?string $cwd = null, ?array $env = null, mixed $input = null, ?int $timeout = 60): Process
|
||||
{
|
||||
if (\is_string($commandline)) {
|
||||
|
||||
Reference in New Issue
Block a user