Skip to content

Commit 8ddf883

Browse files
author
epriestley
committed
Cut Herald rules off at 1GB of diff text
Summary: Ref T4276. When a change is larger than 2GB, PHP can not read the entire change into a string, so Herald can not process it. Additionally, we already have a time limit for practical reasons, but it's huge (probably incorrectly). To deal with these things: - Add an optional byte limit to `diffusion.rawdiffquery`. - Make the query with a 1GB limit. - Reduce the diff timeout from 15 hours to 15 minutes. - Add a "Changeset is enormous" field. This field is true for changes which are too large to process. This generally makes behaviors more sane: - We'll always make progress in Herald in a reasonable amount of time. - Installs can write global rules to handle (or reject) these types of changes. Test Plan: Set limit to 25 bytes instead of 1GB and ran test console on various changes. Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T4276 Differential Revision: https://secure.phabricator.com/D7885
1 parent 972dfa7 commit 8ddf883

File tree

8 files changed

+60
-19
lines changed

8 files changed

+60
-19
lines changed

src/applications/diffusion/conduit/ConduitAPI_diffusion_rawdiffquery_Method.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,37 @@ protected function defineCustomParamTypes() {
2121
'commit' => 'required string',
2222
'path' => 'optional string',
2323
'timeout' => 'optional int',
24+
'byteLimit' => 'optional int',
2425
'linesOfContext' => 'optional int',
2526
'againstCommit' => 'optional string',
2627
);
2728
}
2829

2930
protected function getResult(ConduitAPIRequest $request) {
3031
$drequest = $this->getDiffusionRequest();
31-
$timeout = $request->getValue('timeout');
32-
$lines_of_context = $request->getValue('linesOfContext');
33-
$against_commit = $request->getValue('againstCommit');
3432

3533
$raw_query = DiffusionRawDiffQuery::newFromDiffusionRequest($drequest);
34+
35+
$timeout = $request->getValue('timeout');
3636
if ($timeout !== null) {
3737
$raw_query->setTimeout($timeout);
3838
}
39+
40+
$lines_of_context = $request->getValue('linesOfContext');
3941
if ($lines_of_context !== null) {
4042
$raw_query->setLinesOfContext($lines_of_context);
4143
}
44+
45+
$against_commit = $request->getValue('againstCommit');
4246
if ($against_commit !== null) {
4347
$raw_query->setAgainstCommit($against_commit);
4448
}
49+
50+
$byte_limit = $request->getValue('byteLimit');
51+
if ($byte_limit !== null) {
52+
$raw_query->setByteLimit($byte_limit);
53+
}
54+
4555
return $raw_query->loadRawDiff();
4656
}
4757
}

src/applications/diffusion/query/rawdiff/DiffusionGitRawDiffQuery.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,7 @@ protected function executeQuery() {
3434
$commit,
3535
$path);
3636

37-
if ($this->getTimeout()) {
38-
$future->setTimeout($this->getTimeout());
39-
}
37+
$this->configureFuture($future);
4038

4139
try {
4240
list($raw_diff) = $future->resolvex();
@@ -61,9 +59,7 @@ protected function executeQuery() {
6159
$commit,
6260
$drequest->getPath());
6361

64-
if ($this->getTimeout()) {
65-
$future->setTimeout($this->getTimeout());
66-
}
62+
$this->configureFuture($future);
6763

6864
list($raw_diff) = $future->resolvex();
6965
}

src/applications/diffusion/query/rawdiff/DiffusionMercurialRawDiffQuery.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ protected function executeQuery() {
66
return $this->executeRawDiffCommand();
77
}
88

9-
109
protected function executeRawDiffCommand() {
1110
$drequest = $this->getRequest();
1211
$repository = $drequest->getRepository();
@@ -31,9 +30,7 @@ protected function executeRawDiffCommand() {
3130
$commit,
3231
$path);
3332

34-
if ($this->getTimeout()) {
35-
$future->setTimeout($this->getTimeout());
36-
}
33+
$this->configureFuture($future);
3734

3835
list($raw_diff) = $future->resolvex();
3936

src/applications/diffusion/query/rawdiff/DiffusionRawDiffQuery.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ abstract class DiffusionRawDiffQuery extends DiffusionQuery {
66
private $timeout;
77
private $linesOfContext = 65535;
88
private $againstCommit;
9+
private $byteLimit;
910

1011
final public static function newFromDiffusionRequest(
1112
DiffusionRequest $request) {
@@ -25,6 +26,15 @@ final public function getTimeout() {
2526
return $this->timeout;
2627
}
2728

29+
public function setByteLimit($byte_limit) {
30+
$this->byteLimit = $byte_limit;
31+
return $this;
32+
}
33+
34+
public function getByteLimit() {
35+
return $this->byteLimit;
36+
}
37+
2838
final public function setLinesOfContext($lines_of_context) {
2939
$this->linesOfContext = $lines_of_context;
3040
return $this;
@@ -43,4 +53,15 @@ final public function getAgainstCommit() {
4353
return $this->againstCommit;
4454
}
4555

56+
protected function configureFuture(ExecFuture $future) {
57+
if ($this->getTimeout()) {
58+
$future->setTimeout($this->getTimeout());
59+
}
60+
61+
if ($this->getByteLimit()) {
62+
$future->setStdoutSizeLimit($this->getByteLimit());
63+
$future->setStderrSizeLimit($this->getByteLimit());
64+
}
65+
}
66+
4667
}

src/applications/diffusion/query/rawdiff/DiffusionSvnRawDiffQuery.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ protected function executeQuery() {
2222
$commit,
2323
$repository->getSubversionPathURI($drequest->getPath()));
2424

25-
if ($this->getTimeout()) {
26-
$future->setTimeout($this->getTimeout());
27-
}
25+
$this->configureFuture($future);
2826

2927
list($raw_diff) = $future->resolvex();
3028
return $raw_diff;

src/applications/herald/adapter/HeraldAdapter.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ abstract class HeraldAdapter {
1818
const FIELD_DIFF_CONTENT = 'diff-content';
1919
const FIELD_DIFF_ADDED_CONTENT = 'diff-added-content';
2020
const FIELD_DIFF_REMOVED_CONTENT = 'diff-removed-content';
21+
const FIELD_DIFF_ENORMOUS = 'diff-enormous';
2122
const FIELD_REPOSITORY = 'repository';
2223
const FIELD_REPOSITORY_PROJECTS = 'repository-projects';
2324
const FIELD_RULE = 'rule';
@@ -193,6 +194,7 @@ public function getFieldNameMap() {
193194
self::FIELD_DIFF_CONTENT => pht('Any changed file content'),
194195
self::FIELD_DIFF_ADDED_CONTENT => pht('Any added file content'),
195196
self::FIELD_DIFF_REMOVED_CONTENT => pht('Any removed file content'),
197+
self::FIELD_DIFF_ENORMOUS => pht('Change is enormous'),
196198
self::FIELD_REPOSITORY => pht('Repository'),
197199
self::FIELD_REPOSITORY_PROJECTS => pht('Repository\'s projects'),
198200
self::FIELD_RULE => pht('Another Herald rule'),
@@ -342,6 +344,7 @@ public function getConditionsForField($field) {
342344
self::CONDITION_NOT_EXISTS,
343345
);
344346
case self::FIELD_IS_MERGE_COMMIT:
347+
case self::FIELD_DIFF_ENORMOUS:
345348
return array(
346349
self::CONDITION_IS_TRUE,
347350
self::CONDITION_IS_FALSE,

src/applications/herald/adapter/HeraldCommitAdapter.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ public function getFields() {
9999
self::FIELD_DIFF_CONTENT,
100100
self::FIELD_DIFF_ADDED_CONTENT,
101101
self::FIELD_DIFF_REMOVED_CONTENT,
102+
self::FIELD_DIFF_ENORMOUS,
102103
self::FIELD_RULE,
103104
self::FIELD_AFFECTED_PACKAGE,
104105
self::FIELD_AFFECTED_PACKAGE_OWNER,
@@ -277,14 +278,26 @@ private function loadCommitDiff() {
277278
'commit' => $this->commit->getCommitIdentifier(),
278279
));
279280

281+
$byte_limit = (1024 * 1024 * 1024); // 1GB
282+
280283
$raw = DiffusionQuery::callConduitWithDiffusionRequest(
281284
PhabricatorUser::getOmnipotentUser(),
282285
$drequest,
283286
'diffusion.rawdiffquery',
284287
array(
285288
'commit' => $this->commit->getCommitIdentifier(),
286-
'timeout' => 60 * 60 * 15,
287-
'linesOfContext' => 0));
289+
'timeout' => (60 * 15), // 15 minutes
290+
'byteLimit' => $byte_limit,
291+
'linesOfContext' => 0,
292+
));
293+
294+
if (strlen($raw) >= $byte_limit) {
295+
throw new Exception(
296+
pht(
297+
'The raw text of this change is enormous (larger than %d bytes). '.
298+
'Herald can not process it.',
299+
$byte_limit));
300+
}
288301

289302
$parser = new ArcanistDiffParser();
290303
$changes = $parser->parseDiff($raw);
@@ -360,6 +373,9 @@ public function getHeraldField($field) {
360373
return $this->getDiffContent('+');
361374
case self::FIELD_DIFF_REMOVED_CONTENT:
362375
return $this->getDiffContent('-');
376+
case self::FIELD_DIFF_ENORMOUS:
377+
$this->getDiffContent('*');
378+
return ($this->commitDiff instanceof Exception);
363379
case self::FIELD_AFFECTED_PACKAGE:
364380
$packages = $this->loadAffectedPackages();
365381
return mpull($packages, 'getPHID');

src/applications/herald/storage/HeraldRule.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ final class HeraldRule extends HeraldDAO
1717
protected $isDisabled = 0;
1818
protected $triggerObjectPHID;
1919

20-
protected $configVersion = 24;
20+
protected $configVersion = 25;
2121

2222
// phids for which this rule has been applied
2323
private $ruleApplied = self::ATTACHABLE;

0 commit comments

Comments
 (0)