Path: blob/master/src/applications/diffusion/protocol/DiffusionMercurialCommandEngine.php
12242 views
<?php12final class DiffusionMercurialCommandEngine3extends DiffusionCommandEngine {45protected function canBuildForRepository(6PhabricatorRepository $repository) {7return $repository->isHg();8}910protected function newFormattedCommand($pattern, array $argv) {11$args = array();1213// Crudely blacklist commands which look like they may contain command14// injection via "--config" or "--debugger". See T13012. To do this, we15// print the whole command, parse it using shell rules, then examine each16// argument to see if it looks like "--config" or "--debugger".1718$test_command = call_user_func_array(19'csprintf',20array_merge(array($pattern), $argv));21$test_args = id(new PhutilShellLexer())22->splitArguments($test_command);2324foreach ($test_args as $test_arg) {25if (preg_match('/^--(config|debugger)/i', $test_arg)) {26throw new DiffusionMercurialFlagInjectionException(27pht(28'Mercurial command appears to contain unsafe injected "--config" '.29'or "--debugger": %s',30$test_command));31}32}3334// NOTE: Here, and in Git and Subversion, we override the SSH command even35// if the repository does not use an SSH remote, since our SSH wrapper36// defuses an attack against older versions of Mercurial, Git and37// Subversion (see T12961) and it's possible to execute this attack38// in indirect ways, like by using an SSH subrepo inside an HTTP repo.3940$pattern = "hg --config ui.ssh=%s {$pattern}";41$args[] = $this->getSSHWrapper();4243return array($pattern, array_merge($args, $argv));44}4546protected function newCustomEnvironment() {47$env = array();4849// NOTE: This overrides certain configuration, extensions, and settings50// which make Mercurial commands do random unusual things.51$env['HGPLAIN'] = 1;5253return $env;54}5556/**57* Sanitize output of an `hg` command invoked with the `--debug` flag to make58* it usable.59*60* @param string Output from `hg --debug ...`61* @return string Usable output.62*/63public static function filterMercurialDebugOutput($stdout) {64// When hg commands are run with `--debug` and some config file isn't65// trusted, Mercurial prints out a warning to stdout, twice, after Feb 2011.66//67// http://selenic.com/pipermail/mercurial-devel/2011-February/028541.html68//69// After Jan 2015, it may also fail to write to a revision branch cache.70//71// Separately, it may fail to write to a different branch cache, and may72// encounter issues reading the branch cache.73//74// When Mercurial repositories are hosted on external systems with75// multi-user environments it's possible that the branch cache is computed76// on a revision which does not end up being published. When this happens it77// will recompute the cache but also print out "invalid branch cache".78//79// https://www.mercurial-scm.org/pipermail/mercurial/2014-June/047239.html80//81// When observing a repository which uses largefiles, the debug output may82// also contain extraneous output about largefile changes.83//84// At some point Mercurial added/improved support for pager used when85// command output is large. It includes printing out debug information that86// the pager is being started for a command. This seems to happen despite87// the output of the command being piped/read from another process.88//89// When printing color output Mercurial may run into some issue with the90// terminal info. This should never happen in Phabricator since color91// output should be turned off, however in the event it shows up we should92// filter it out anyways.9394$ignore = array(95'ignoring untrusted configuration option',96"couldn't write revision branch cache:",97"couldn't write branch cache:",98'invalid branchheads cache',99'invalid branch cache',100'updated patterns: .hglf',101'starting pager for command',102'no terminfo entry for',103);104105foreach ($ignore as $key => $pattern) {106$ignore[$key] = preg_quote($pattern, '/');107}108109$ignore = '('.implode('|', $ignore).')';110111$lines = preg_split('/(?<=\n)/', $stdout);112$regex = '/'.$ignore.'.*\n$/';113114foreach ($lines as $key => $line) {115$lines[$key] = preg_replace($regex, '', $line);116}117118return implode('', $lines);119}120121}122123124