Skip to content
Snippets Groups Projects
Commit d5de6e4f authored by Dan Villiom Podlaski Christiansen's avatar Dan Villiom Podlaski Christiansen
Browse files

hg2git: refactor, extract doctests to testsuite

The doctests are hard to read & modify.
parent 626b0fa3
No related branches found
No related tags found
No related merge requests found
......@@ -29,57 +29,6 @@
return sub, substate
def audit_git_path(ui, path):
r"""Check for path components that case-fold to .git.
>>> from mercurial import pycompat
>>> class fakeui(object):
... def configbool(*args):
... return False
... def warn(self, s):
... if pycompat.ispy3:
... import sys
... print(s.decode('utf-8', 'surrogatepass'))
... else:
... print(s)
>>> u = fakeui()
>>> audit_git_path(u, b'foo/git~100/wat')
... # doctest: +ELLIPSIS
warning: path 'foo/git~100/wat' contains a potentially dangerous ...
It may not be legal to check out in Git.
It may also be rejected by some git server configurations.
<BLANKLINE>
>>> audit_git_path(u, u'foo/.gi\u200ct'.encode('utf-8'))
... # doctest: +ELLIPSIS
warning: path 'foo/.gi‌t' contains a potentially dangerous ...
It may not be legal to check out in Git.
It may also be rejected by some git server configurations.
<BLANKLINE>
>>> audit_git_path(u, b'this/is/safe')
"""
dangerous = False
for c in path.split(b'/'):
if encoding.hfsignoreclean(c) == b'.git':
dangerous = True
break
elif b'~' in c:
base, tail = c.split(b'~', 1)
if tail.isdigit() and base.upper().startswith(b'GIT'):
dangerous = True
break
if dangerous:
if compat.config(ui, b'bool', b'git', b'blockdotgit'):
raise error.Abort(
(b"Refusing to export likely-dangerous path '%s'" % path),
hint=(b"If you need to continue, read about CVE-2014-9390 and "
b"then set '[git] blockdotgit = false' in your hgrc."))
ui.warn(b"warning: path '%s' contains a potentially dangerous path "
b'component.\n'
b'It may not be legal to check out in Git.\n'
b'It may also be rejected by some git server configurations.\n'
% path)
class IncrementalChangesetExporter(object):
"""Incrementally export Mercurial changesets to Git trees.
......@@ -166,6 +115,52 @@
"""
return self._dirs[b''].id
def _audit_one_path(self, path):
r"""Check for path components that case-fold to .git.
Returns ``True`` for normal paths. The results for insecure
paths depend on the configuration in ``ui``:
If ``git.blockdotgit`` is set, insecure paths raise an
exception.
Otherwise, a warning may be printed, but the return value is
``True``, indicating that all paths should be retained
regardless of any problems they may cause.
"""
ui = self._hg.ui
dangerous = False
for c in path.split(b'/'):
if encoding.hfsignoreclean(c) == b'.git':
dangerous = True
break
elif b'~' in c:
base, tail = c.split(b'~', 1)
if tail.isdigit() and base.upper().startswith(b'GIT'):
dangerous = True
break
if dangerous:
if compat.config(ui, b'bool', b'git', b'blockdotgit'):
raise error.Abort(
b"Refusing to export likely-dangerous path '%s'" % path,
hint=(b'If you need to continue, read about '
b'CVE-2014-9390 and then set '
b"'[git] blockdotgit = false' in your hgrc."))
ui.warn(b"warning: path '%s' contains a potentially dangerous "
b'path component.\n'
b'It may not be legal to check out in Git.\n'
b'It may also be rejected by some git server '
b'configurations.\n'
% path)
def audit_paths(self, paths):
"""Handle insecure paths"""
for path in paths:
self._audit_one_path(path)
return paths
def update_changeset(self, newctx):
"""Set the tree to track a new Mercurial changeset.
......@@ -201,10 +196,8 @@
# the full manifest. And, the easy way to compare two manifests is
# localrepo.status().
status = self._hg.status(self._ctx, newctx)
modified, added, removed = (
status.modified,
status.added,
status.removed,
modified, added, removed = map(
self.audit_paths, (status.modified, status.added, status.removed),
)
# We track which directories/trees have modified in this update and we
......@@ -239,7 +232,6 @@
# corresponding Git blob and its tree entry. We emit the blob
# immediately and update trees to be aware of its presence.
for path in set(modified) | set(added):
audit_git_path(self._hg.ui, path)
if path == b'.hgsubstate' or path == b'.hgsub':
continue
......
......@@ -11,6 +11,12 @@
> #!/bin/sh
> echo pwned
> EOF
$ python - foo/git~100/wat bar/.gi\\u200ct/wut this/is/safe <<EOF
> import os, sys
> for p in sys.argv[1:]:
> p = p.encode('ascii').decode('unicode_escape').encode('utf-8')
> os.makedirs(os.path.dirname(p))
> open(p, 'w')
> EOF
$ hg addremove
adding .git/hooks/post-update
......@@ -15,8 +21,11 @@
$ hg addremove
adding .git/hooks/post-update
adding bar/.gi\xe2\x80\x8ct/wut (esc)
adding foo/git~100/wat
adding this/is/safe
$ hg ci -m "we should refuse to export this"
$ hg book master
$ hg gexport
abort: Refusing to export likely-dangerous path '.git/hooks/post-update'
(If you need to continue, read about CVE-2014-9390 and then set '[git] blockdotgit = false' in your hgrc.)
[255]
......@@ -17,9 +26,24 @@
$ hg ci -m "we should refuse to export this"
$ hg book master
$ hg gexport
abort: Refusing to export likely-dangerous path '.git/hooks/post-update'
(If you need to continue, read about CVE-2014-9390 and then set '[git] blockdotgit = false' in your hgrc.)
[255]
$ hg gexport --config git.blockdotgit=no
warning: path '.git/hooks/post-update' contains a potentially dangerous path component.
It may not be legal to check out in Git.
It may also be rejected by some git server configurations.
warning: path 'bar/.gi\xe2\x80\x8ct/wut' contains a potentially dangerous path component. (esc)
It may not be legal to check out in Git.
It may also be rejected by some git server configurations.
warning: path 'foo/git~100/wat' contains a potentially dangerous path component.
It may not be legal to check out in Git.
It may also be rejected by some git server configurations.
$ GIT_DIR=.hg/git git ls-tree -r --name-only master
.git/hooks/post-update
"bar/.gi\342\200\214t/wut"
foo/git~100/wat
this/is/safe
$ cd ..
$ rm -rf hg
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment