Prevent enormous changes from being pushed to repositoires by default

Summary:
Fixes T13031. "Enormous" changes are basically changes which are too large to hold in memory, although the actual definition we use today is "more than 1GB of change text or `git diff` runs for more than 15 minutes".

If an install configures a Herald content rule like "when content matches /XYZ/, do something" and then a user pushes a 30 GB source file, we can't put it into memory to `preg_match()` it. Currently, the way to handle this case is to write a separate Herald rule that rejects enormous changes. However, this isn't obvious and means the default behavior is unsafe.

Make the default behavior safe by rejecting these changes with a message, similar to how we reject "dangerous" changes (which permanently delete or overwrite history) by default.

Also, change a couple of UI strings from "Enormous" to "Very Large" to reduce ambiguity. See <https://discourse.phabricator-community.org/t/herald-enormous-check/822>.

Test Plan: Changed the definition of "enormous" from 1GB to 1 byte. Pushed a change; got rejected. Allowed enormous changes, pushed, got rejected by a Herald rule. Disabled the Herald rule, pushed, got a clean push. Prevented enormous changes again. Grepped for "enormous" elsewhere in the UI.

Reviewers: amckinley

Reviewed By: amckinley

Subscribers: joshuaspence

Maniphest Tasks: T13031

Differential Revision: https://secure.phabricator.com/D18850
This commit is contained in:
epriestley
2017-12-26 10:38:45 -08:00
parent cb957f8d62
commit 53b25db918
13 changed files with 233 additions and 8 deletions

View File

@@ -277,9 +277,9 @@ final class DiffusionCommitController extends DiffusionController {
'This commit is empty and does not affect any paths.'));
} else if ($was_limited) {
$info_panel = $this->renderStatusMessage(
pht('Enormous Commit'),
pht('Very Large Commit'),
pht(
'This commit is enormous, and affects more than %d files. '.
'This commit is very large, and affects more than %d files. '.
'Changes are not shown.',
$hard_limit));
} else if (!$this->getCommitExists()) {

View File

@@ -0,0 +1,90 @@
<?php
final class DiffusionRepositoryEditEnormousController
extends DiffusionRepositoryManageController {
public function handleRequest(AphrontRequest $request) {
$response = $this->loadDiffusionContextForEdit();
if ($response) {
return $response;
}
$viewer = $this->getViewer();
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$panel_uri = id(new DiffusionRepositoryBasicsManagementPanel())
->setRepository($repository)
->getPanelURI();
if (!$repository->canAllowEnormousChanges()) {
return $this->newDialog()
->setTitle(pht('Unprotectable Repository'))
->appendParagraph(
pht(
'This repository can not be protected from enormous changes '.
'because Phabricator does not control what users are allowed '.
'to push to it.'))
->addCancelButton($panel_uri);
}
if ($request->isFormPost()) {
$xaction = id(new PhabricatorRepositoryTransaction())
->setTransactionType(PhabricatorRepositoryTransaction::TYPE_ENORMOUS)
->setNewValue(!$repository->shouldAllowEnormousChanges());
$editor = id(new PhabricatorRepositoryEditor())
->setContinueOnNoEffect(true)
->setContentSourceFromRequest($request)
->setActor($viewer)
->applyTransactions($repository, array($xaction));
return id(new AphrontReloadResponse())->setURI($panel_uri);
}
if ($repository->shouldAllowEnormousChanges()) {
$title = pht('Prevent Enormous Changes');
$body = pht(
'It will no longer be possible to push enormous changes to this '.
'repository.');
$submit = pht('Prevent Enormous Changes');
} else {
$title = pht('Allow Enormous Changes');
$body = array(
pht(
'If you allow enormous changes, users can push commits which are '.
'too large for Herald to process content rules for. This can allow '.
'users to evade content rules implemented in Herald.'),
pht(
'You can selectively configure Herald by adding rules to prevent a '.
'subset of enormous changes (for example, based on who is trying '.
'to push the change).'),
);
$submit = pht('Allow Enormous Changes');
}
$more_help = pht(
'Enormous changes are commits which are too large to process with '.
'content rules because: the diff text for the change is larger than '.
'%s bytes; or the diff text takes more than %s seconds to extract.',
new PhutilNumber(HeraldCommitAdapter::getEnormousByteLimit()),
new PhutilNumber(HeraldCommitAdapter::getEnormousTimeLimit()));
$response = $this->newDialog();
foreach ((array)$body as $paragraph) {
$response->appendParagraph($paragraph);
}
return $response
->setTitle($title)
->appendParagraph($more_help)
->addSubmitButton($submit)
->addCancelButton($panel_uri);
}
}