Skip to content

Commit

Permalink
[Process] Use %PATH% before %CD% to load the shell on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-grekas committed Nov 4, 2024
1 parent 46c203f commit 05c2ccc
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 20 deletions.
14 changes: 8 additions & 6 deletions ExecutableFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
*/
class ExecutableFinder
{
private $suffixes = ['.exe', '.bat', '.cmd', '.com'];
private const CMD_BUILTINS = [
'assoc', 'break', 'call', 'cd', 'chdir', 'cls', 'color', 'copy', 'date',
'del', 'dir', 'echo', 'endlocal', 'erase', 'exit', 'for', 'ftype', 'goto',
Expand All @@ -28,6 +27,8 @@ class ExecutableFinder
'setlocal', 'shift', 'start', 'time', 'title', 'type', 'ver', 'vol',
];

private $suffixes = [];

/**
* Replaces default suffixes of executable.
*/
Expand Down Expand Up @@ -65,11 +66,13 @@ public function find(string $name, ?string $default = null, array $extraDirs = [
$extraDirs
);

$suffixes = [''];
$suffixes = [];
if ('\\' === \DIRECTORY_SEPARATOR) {
$pathExt = getenv('PATHEXT');
$suffixes = array_merge($pathExt ? explode(\PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes);
$suffixes = $this->suffixes;
$suffixes = array_merge($suffixes, $pathExt ? explode(\PATH_SEPARATOR, $pathExt) : ['.exe', '.bat', '.cmd', '.com']);
}
$suffixes = '' !== pathinfo($name, PATHINFO_EXTENSION) ? array_merge([''], $suffixes) : array_merge($suffixes, ['']);
foreach ($suffixes as $suffix) {
foreach ($dirs as $dir) {
if ('' === $dir) {
Expand All @@ -85,12 +88,11 @@ public function find(string $name, ?string $default = null, array $extraDirs = [
}
}

if (!\function_exists('exec') || \strlen($name) !== strcspn($name, '/'.\DIRECTORY_SEPARATOR)) {
if ('\\' === \DIRECTORY_SEPARATOR || !\function_exists('exec') || \strlen($name) !== strcspn($name, '/'.\DIRECTORY_SEPARATOR)) {
return $default;
}

$command = '\\' === \DIRECTORY_SEPARATOR ? 'where %s 2> NUL' : 'command -v -- %s';
$execResult = exec(\sprintf($command, escapeshellarg($name)));
$execResult = exec('command -v -- '.escapeshellarg($name));

if (($executablePath = substr($execResult, 0, strpos($execResult, \PHP_EOL) ?: null)) && @is_executable($executablePath)) {
return $executablePath;
Expand Down
15 changes: 2 additions & 13 deletions PhpExecutableFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,8 @@ public function __construct()
public function find(bool $includeArgs = true)
{
if ($php = getenv('PHP_BINARY')) {
if (!is_executable($php)) {
if (!\function_exists('exec') || \strlen($php) !== strcspn($php, '/'.\DIRECTORY_SEPARATOR)) {
return false;
}

$command = '\\' === \DIRECTORY_SEPARATOR ? 'where %s 2> NUL' : 'command -v -- %s';
$execResult = exec(\sprintf($command, escapeshellarg($php)));
if (!$php = substr($execResult, 0, strpos($execResult, \PHP_EOL) ?: null)) {
return false;
}
if (!is_executable($php)) {
return false;
}
if (!is_executable($php) && !$php = $this->executableFinder->find($php)) {
return false;
}

if (@is_dir($php)) {
Expand Down
9 changes: 8 additions & 1 deletion Process.php
Original file line number Diff line number Diff line change
Expand Up @@ -1592,7 +1592,14 @@ function ($m) use (&$env, &$varCache, &$varCount, $uid) {
$cmd
);

$cmd = 'cmd /V:ON /E:ON /D /C ('.str_replace("\n", ' ', $cmd).')';
static $comSpec;

if (!$comSpec && $comSpec = (new ExecutableFinder())->find('cmd.exe')) {
// Escape according to CommandLineToArgvW rules
$comSpec = '"'.preg_replace('{(\\\\*+)"}', '$1$1\"', $comSpec) .'"';
}

$cmd = ($comSpec ?? 'cmd').' /V:ON /E:ON /D /C ('.str_replace("\n", ' ', $cmd).')';
foreach ($this->processPipes->getFiles() as $offset => $filename) {
$cmd .= ' '.$offset.'>"'.$filename.'"';
}
Expand Down

0 comments on commit 05c2ccc

Please sign in to comment.