Merge "Add a sanity check for all refs returned by Gerrit"

This commit is contained in:
Zuul 2018-10-23 15:03:14 +00:00 committed by Gerrit Code Review
commit 76f02e3318
2 changed files with 46 additions and 1 deletions

View File

@ -78,6 +78,35 @@ class TestGerrit(BaseTestCase):
expected_patches = 5
self.run_query(files, expected_patches)
def test_ref_name_check_rules(self):
# See man git-check-ref-format for the rules referenced here
test_strings = [
('refs/heads/normal', True),
('refs/heads/.bad', False), # rule 1
('refs/heads/bad.lock', False), # rule 1
('refs/heads/good.locked', True),
('refs/heads/go.od', True),
('refs/heads//bad', False), # rule 6
('refs/heads/b?d', False), # rule 5
('refs/heads/b[d', False), # rule 5
('refs/heads/b..ad', False), # rule 3
('bad', False), # rule 2
('refs/heads/\nbad', False), # rule 4
('/refs/heads/bad', False), # rule 6
('refs/heads/bad/', False), # rule 6
('refs/heads/bad.', False), # rule 7
('.refs/heads/bad', False), # rule 1
('refs/he@{ads/bad', False), # rule 8
('@', False), # rule 9
('refs\\heads/bad', False) # rule 10
]
for ref, accepted in test_strings:
self.assertEqual(
accepted,
GerritConnection._checkRefFormat(ref),
ref + ' shall be ' + ('accepted' if accepted else 'rejected'))
class TestGerritWeb(ZuulTestCase):
config_file = 'zuul-gerrit-web.conf'

View File

@ -15,6 +15,7 @@
import json
import re
import re2
import select
import threading
import time
@ -290,6 +291,9 @@ class GerritConnection(BaseConnection):
iolog = logging.getLogger("zuul.GerritConnection.io")
depends_on_re = re.compile(r"^Depends-On: (I[0-9a-f]{40})\s*$",
re.MULTILINE | re.IGNORECASE)
refname_bad_sequences = re2.compile(
r"[ \\*\[?:^~\x00-\x1F\x7F]|" # Forbidden characters
r"@{|\.\.|\.$|^@$|/$|^/|//+") # everything else we can check with re2
replication_timeout = 300
replication_retry_interval = 5
@ -776,6 +780,17 @@ class GerritConnection(BaseConnection):
(record.get('number'),))
return changes
@staticmethod
def _checkRefFormat(refname: str) -> bool:
# These are the requirements for valid ref names as per
# man git-check-ref-format
parts = refname.split('/')
return \
(GerritConnection.refname_bad_sequences.search(refname) is None and
len(parts) > 1 and
not any(part.startswith('.') or part.endswith('.lock')
for part in parts))
def getProjectBranches(self, project: Project, tenant) -> List[str]:
branches = self._project_branch_cache.get(project.name)
if branches is not None:
@ -783,7 +798,8 @@ class GerritConnection(BaseConnection):
refs = self.getInfoRefs(project)
heads = [str(k[len('refs/heads/'):]) for k in refs.keys()
if k.startswith('refs/heads/')]
if k.startswith('refs/heads/') and
GerritConnection._checkRefFormat(k)]
self._project_branch_cache[project.name] = heads
return heads