Refine checks against "cwd" before "proc_open()"
Summary:
See PHI1094. Previously, see D15785. Fixes T10853. Upstream: https://bugs.php.net/bug.php?id=77656.
PHP allows you to proc_open() into any CWD, including one that does not exist, is not readable, and/or is not executable.
We attempt to catch this, but don't do enough checks, and allow you to attempt execution into a directory which exists but which you can't read or execute.
Add more checks to prevent this. Also, try to make assertExists() more clever about cases where a path really doesn't exist versus cases where we aren't allowed to tell if a path exists or not because of a permissions issue.
(It's technically legal to chdir() into a directory you only have +x on, although this is probably ill-advised.)
Test Plan:
Used this script with various arguments:
<?php require_once '/Users/epriestley/dev/phabricator/scripts/init/init-script.php'; $result = id(new ExecFuture('pwd && ls -alh')) ->setCWD($argv[1]) ->resolvex(); var_dump($result);
In all cases, the directory name describes the permissions. subdir/ exists and is a directory we have "+r" and "+x" on.
epriestley@orbital ~/scratch $ php -f pwd2.php /Users/epriestley/scratch/not-readable [2019-02-22 15:34:14] EXCEPTION: (Exception) Preparing to run a command in directory "/Users/epriestley/scratch/not-readable", but that directory is not readable (the current process does not have "+r" permission). at [<phutil>/src/future/exec/PhutilExecutableFuture.php:156]
epriestley@orbital ~/scratch $ php -f pwd2.php /Users/epriestley/scratch/not-readable/subdir array(2) { [0]=> string(163) "/Users/epriestley/scratch/not-readable/subdir total 0 drwxr-xr-x 2 epriestley staff 64B Feb 22 15:33 . drwxr-x--x 3 root wheel 96B Feb 22 15:33 .. " [1]=> string(0) "" }
epriestley@orbital ~/scratch $ php -f pwd2.php /Users/epriestley/scratch/not-executable [2019-02-22 15:34:24] EXCEPTION: (Exception) Preparing to run a command in directory "/Users/epriestley/scratch/not-executable", but that directory is not executable (the current process does not have "+x" permission). at [<phutil>/src/future/exec/PhutilExecutableFuture.php:165]
epriestley@orbital ~/scratch $ php -f pwd2.php /Users/epriestley/scratch/not-executable/subdir [2019-02-22 15:34:26] EXCEPTION: (PhutilProxyException) Unable to run a command in directory "/Users/epriestley/scratch/not-executable/subdir". {>} (FilesystemException) Filesystem path "/Users/epriestley/scratch/not-executable/subdir" can not be accessed because a parent directory ("/Users/epriestley/scratch/not-executable") is not executable (the current process does not have "+x" permission). at [<phutil>/src/filesystem/Filesystem.php:1142]
epriestley@orbital ~/scratch $ php -f pwd2.php /Users/epriestley/scratch/not-readable-or-executable/ [2019-02-22 15:34:32] EXCEPTION: (Exception) Preparing to run a command in directory "/Users/epriestley/scratch/not-readable-or-executable/", but that directory is not readable (the current process does not have "+r" permission). at [<phutil>/src/future/exec/PhutilExecutableFuture.php:156]
epriestley@orbital ~/scratch $ php -f pwd2.php /Users/epriestley/scratch/not-readable-or-executable/subdir [2019-02-22 15:34:33] EXCEPTION: (PhutilProxyException) Unable to run a command in directory "/Users/epriestley/scratch/not-readable-or-executable/subdir". {>} (FilesystemException) Filesystem path "/Users/epriestley/scratch/not-readable-or-executable/subdir" can not be accessed because a parent directory ("/Users/epriestley/scratch/not-readable-or-executable") is not executable (the current process does not have "+x" permission). at [<phutil>/src/filesystem/Filesystem.php:1142]
epriestley@orbital ~/scratch $ php -f pwd2.php /Users/epriestley/scratch/does-not-exist [2019-02-22 15:34:37] EXCEPTION: (PhutilProxyException) Unable to run a command in directory "/Users/epriestley/scratch/does-not-exist". {>} (FilesystemException) Filesystem path "/Users/epriestley/scratch/does-not-exist" does not exist. at [<phutil>/src/filesystem/Filesystem.php:1153]
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10853
Differential Revision: https://secure.phabricator.com/D20205