Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/diffusion/protocol/DiffusionMercurialCommandEngine.php
12242 views
1
<?php
2
3
final class DiffusionMercurialCommandEngine
4
extends DiffusionCommandEngine {
5
6
protected function canBuildForRepository(
7
PhabricatorRepository $repository) {
8
return $repository->isHg();
9
}
10
11
protected function newFormattedCommand($pattern, array $argv) {
12
$args = array();
13
14
// Crudely blacklist commands which look like they may contain command
15
// injection via "--config" or "--debugger". See T13012. To do this, we
16
// print the whole command, parse it using shell rules, then examine each
17
// argument to see if it looks like "--config" or "--debugger".
18
19
$test_command = call_user_func_array(
20
'csprintf',
21
array_merge(array($pattern), $argv));
22
$test_args = id(new PhutilShellLexer())
23
->splitArguments($test_command);
24
25
foreach ($test_args as $test_arg) {
26
if (preg_match('/^--(config|debugger)/i', $test_arg)) {
27
throw new DiffusionMercurialFlagInjectionException(
28
pht(
29
'Mercurial command appears to contain unsafe injected "--config" '.
30
'or "--debugger": %s',
31
$test_command));
32
}
33
}
34
35
// NOTE: Here, and in Git and Subversion, we override the SSH command even
36
// if the repository does not use an SSH remote, since our SSH wrapper
37
// defuses an attack against older versions of Mercurial, Git and
38
// Subversion (see T12961) and it's possible to execute this attack
39
// in indirect ways, like by using an SSH subrepo inside an HTTP repo.
40
41
$pattern = "hg --config ui.ssh=%s {$pattern}";
42
$args[] = $this->getSSHWrapper();
43
44
return array($pattern, array_merge($args, $argv));
45
}
46
47
protected function newCustomEnvironment() {
48
$env = array();
49
50
// NOTE: This overrides certain configuration, extensions, and settings
51
// which make Mercurial commands do random unusual things.
52
$env['HGPLAIN'] = 1;
53
54
return $env;
55
}
56
57
/**
58
* Sanitize output of an `hg` command invoked with the `--debug` flag to make
59
* it usable.
60
*
61
* @param string Output from `hg --debug ...`
62
* @return string Usable output.
63
*/
64
public static function filterMercurialDebugOutput($stdout) {
65
// When hg commands are run with `--debug` and some config file isn't
66
// trusted, Mercurial prints out a warning to stdout, twice, after Feb 2011.
67
//
68
// http://selenic.com/pipermail/mercurial-devel/2011-February/028541.html
69
//
70
// After Jan 2015, it may also fail to write to a revision branch cache.
71
//
72
// Separately, it may fail to write to a different branch cache, and may
73
// encounter issues reading the branch cache.
74
//
75
// When Mercurial repositories are hosted on external systems with
76
// multi-user environments it's possible that the branch cache is computed
77
// on a revision which does not end up being published. When this happens it
78
// will recompute the cache but also print out "invalid branch cache".
79
//
80
// https://www.mercurial-scm.org/pipermail/mercurial/2014-June/047239.html
81
//
82
// When observing a repository which uses largefiles, the debug output may
83
// also contain extraneous output about largefile changes.
84
//
85
// At some point Mercurial added/improved support for pager used when
86
// command output is large. It includes printing out debug information that
87
// the pager is being started for a command. This seems to happen despite
88
// the output of the command being piped/read from another process.
89
//
90
// When printing color output Mercurial may run into some issue with the
91
// terminal info. This should never happen in Phabricator since color
92
// output should be turned off, however in the event it shows up we should
93
// filter it out anyways.
94
95
$ignore = array(
96
'ignoring untrusted configuration option',
97
"couldn't write revision branch cache:",
98
"couldn't write branch cache:",
99
'invalid branchheads cache',
100
'invalid branch cache',
101
'updated patterns: .hglf',
102
'starting pager for command',
103
'no terminfo entry for',
104
);
105
106
foreach ($ignore as $key => $pattern) {
107
$ignore[$key] = preg_quote($pattern, '/');
108
}
109
110
$ignore = '('.implode('|', $ignore).')';
111
112
$lines = preg_split('/(?<=\n)/', $stdout);
113
$regex = '/'.$ignore.'.*\n$/';
114
115
foreach ($lines as $key => $line) {
116
$lines[$key] = preg_replace($regex, '', $line);
117
}
118
119
return implode('', $lines);
120
}
121
122
}
123
124