diff --git a/.hgsigs b/.hgsigs --- a/.hgsigs +++ b/.hgsigs @@ -154,3 +154,4 @@ 920977f72c7b70acfdaf56ab35360584d7845827 2f427b57bf9019c6dc3750baa539dc22c1be50f6 0 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 diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -167,3 +167,4 @@ 920977f72c7b70acfdaf56ab35360584d7845827 2f427b57bf9019c6dc3750baa539dc22c1be50f6 4.3.3 1e2454b60e5936f5e77498cab2648db469504487 4.4-rc 0ccb43d4cf01d013ae05917ec4f305509f851b2d 4.4 +cabc840ffdee8a72f3689fb77dd74d04fdc2bc04 4.4.1 diff --git a/hgext/share.py b/hgext/share.py --- a/hgext/share.py +++ b/hgext/share.py @@ -63,16 +63,6 @@ command = registrar.command(cmdtable) # leave the attribute unspecified. testedwith = 'ships-with-hg-core' -configtable = {} -configitem = registrar.configitem(configtable) - -configitem('share', 'pool', - default=None, -) -configitem('share', 'poolnaming', - default='identity', -) - @command('share', [('U', 'noupdate', None, _('do not create a working directory')), ('B', 'bookmarks', None, _('also share bookmarks')), diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -570,9 +570,8 @@ def _conflictsmsg(repo): unresolvedlist = [f for f in mergestate.unresolved() if m(f)] if unresolvedlist: mergeliststr = '\n'.join( - [' %s' % os.path.relpath( - os.path.join(repo.root, path), - pycompat.getcwd()) for path in unresolvedlist]) + [' %s' % util.pathto(repo.root, pycompat.getcwd(), path) + for path in unresolvedlist]) msg = _('''Unresolved merge conflicts: %s diff --git a/mercurial/configitems.py b/mercurial/configitems.py --- a/mercurial/configitems.py +++ b/mercurial/configitems.py @@ -787,6 +787,12 @@ coreconfigitem('server', 'validate', coreconfigitem('server', 'zliblevel', default=-1, ) +coreconfigitem('share', 'pool', + default=None, +) +coreconfigitem('share', 'poolnaming', + default='identity', +) coreconfigitem('smtp', 'host', default=None, ) @@ -808,6 +814,18 @@ coreconfigitem('smtp', 'username', coreconfigitem('sparse', 'missingwarning', default=True, ) +coreconfigitem('subrepos', 'allowed', + default=dynamicdefault, # to make backporting simpler +) +coreconfigitem('subrepos', 'hg:allowed', + default=dynamicdefault, +) +coreconfigitem('subrepos', 'git:allowed', + default=dynamicdefault, +) +coreconfigitem('subrepos', 'svn:allowed', + default=dynamicdefault, +) coreconfigitem('templates', '.*', default=None, generic=True, diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt --- a/mercurial/help/config.txt +++ b/mercurial/help/config.txt @@ -1893,6 +1893,47 @@ rewrite rules are then applied on the fu doesn't match the full path, an attempt is made to apply it on the relative path alone. The rules are applied in definition order. +``subrepos`` +------------ + +This section contains options that control the behavior of the +subrepositories feature. See also :hg:`help subrepos`. + +Security note: auditing in Mercurial is known to be insufficient to +prevent clone-time code execution with carefully constructed Git +subrepos. It is unknown if a similar detect is present in Subversion +subrepos. Both Git and Subversion subrepos are disabled by default +out of security concerns. These subrepo types can be enabled using +the respective options below. + +``allowed`` + Whether subrepositories are allowed in the working directory. + + When false, commands involving subrepositories (like :hg:`update`) + will fail for all subrepository types. + (default: true) + +``hg:allowed`` + Whether Mercurial subrepositories are allowed in the working + directory. This option only has an effect if ``subrepos.allowed`` + is true. + (default: true) + +``git:allowed`` + Whether Git subrepositories are allowed in the working directory. + This option only has an effect if ``subrepos.allowed`` is true. + + See the security note above before enabling Git subrepos. + (default: false) + +``svn:allowed`` + Whether Subversion subrepositories are allowed in the working + directory. This option only has an effect if ``subrepos.allowed`` + is true. + + See the security note above before enabling Subversion subrepos. + (default: false) + ``templatealias`` ----------------- diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -243,7 +243,9 @@ def share(ui, source, dest=None, update= try: sharedpath = os.path.relpath(sharedpath, destvfs.base) requirements += 'relshared\n' - except IOError as e: + except (IOError, ValueError) as e: + # ValueError is raised on Windows if the drive letters differ on + # each path raise error.Abort(_('cannot calculate relative path'), hint=str(e)) else: diff --git a/mercurial/pathutil.py b/mercurial/pathutil.py --- a/mercurial/pathutil.py +++ b/mercurial/pathutil.py @@ -135,7 +135,47 @@ class pathauditor(object): return False def canonpath(root, cwd, myname, auditor=None): - '''return the canonical path of myname, given cwd and root''' + '''return the canonical path of myname, given cwd and root + + >>> def check(root, cwd, myname): + ... a = pathauditor(root, realfs=False) + ... try: + ... return canonpath(root, cwd, myname, a) + ... except error.Abort: + ... return 'aborted' + >>> def unixonly(root, cwd, myname, expected='aborted'): + ... if pycompat.iswindows: + ... return expected + ... return check(root, cwd, myname) + >>> def winonly(root, cwd, myname, expected='aborted'): + ... if not pycompat.iswindows: + ... return expected + ... return check(root, cwd, myname) + >>> winonly(b'd:\\\\repo', b'c:\\\\dir', b'filename') + 'aborted' + >>> winonly(b'c:\\\\repo', b'c:\\\\dir', b'filename') + 'aborted' + >>> winonly(b'c:\\\\repo', b'c:\\\\', b'filename') + 'aborted' + >>> winonly(b'c:\\\\repo', b'c:\\\\', b'repo\\\\filename', + ... b'filename') + 'filename' + >>> winonly(b'c:\\\\repo', b'c:\\\\repo', b'filename', b'filename') + 'filename' + >>> winonly(b'c:\\\\repo', b'c:\\\\repo\\\\subdir', b'filename', + ... b'subdir/filename') + 'subdir/filename' + >>> unixonly(b'/repo', b'/dir', b'filename') + 'aborted' + >>> unixonly(b'/repo', b'/', b'filename') + 'aborted' + >>> unixonly(b'/repo', b'/', b'repo/filename', b'filename') + 'filename' + >>> unixonly(b'/repo', b'/repo', b'filename', b'filename') + 'filename' + >>> unixonly(b'/repo', b'/repo/subdir', b'filename', b'subdir/filename') + 'subdir/filename' + ''' if util.endswithsep(root): rootsep = root else: diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -359,6 +359,33 @@ def _sanitize(ui, vfs, ignore): "in '%s'\n") % vfs.join(dirname)) vfs.unlink(vfs.reljoin(dirname, f)) +def _auditsubrepopath(repo, path): + # auditor doesn't check if the path itself is a symlink + pathutil.pathauditor(repo.root)(path) + if repo.wvfs.islink(path): + raise error.Abort(_("subrepo '%s' traverses symbolic link") % path) + +SUBREPO_ALLOWED_DEFAULTS = { + 'hg': True, + 'git': False, + 'svn': False, +} + +def _checktype(ui, kind): + # subrepos.allowed is a master kill switch. If disabled, subrepos are + # disabled period. + if not ui.configbool('subrepos', 'allowed', True): + raise error.Abort(_('subrepos not enabled'), + hint=_("see 'hg help config.subrepos' for details")) + + default = SUBREPO_ALLOWED_DEFAULTS.get(kind, False) + if not ui.configbool('subrepos', '%s:allowed' % kind, default): + raise error.Abort(_('%s subrepos not allowed') % kind, + hint=_("see 'hg help config.subrepos' for details")) + + if kind not in types: + raise error.Abort(_('unknown subrepo type %s') % kind) + def subrepo(ctx, path, allowwdir=False, allowcreate=True): """return instance of the right subrepo class for subrepo in path""" # subrepo inherently violates our import layering rules @@ -369,10 +396,10 @@ def subrepo(ctx, path, allowwdir=False, from . import hg as h hg = h - pathutil.pathauditor(ctx.repo().root)(path) + repo = ctx.repo() + _auditsubrepopath(repo, path) state = ctx.substate[path] - if state[2] not in types: - raise error.Abort(_('unknown subrepo type %s') % state[2]) + _checktype(repo.ui, state[2]) if allowwdir: state = (state[0], ctx.subrev(path), state[2]) return types[state[2]](ctx, path, state[:2], allowcreate) @@ -387,10 +414,10 @@ def nullsubrepo(ctx, path, pctx): from . import hg as h hg = h - pathutil.pathauditor(ctx.repo().root)(path) + repo = ctx.repo() + _auditsubrepopath(repo, path) state = ctx.substate[path] - if state[2] not in types: - raise error.Abort(_('unknown subrepo type %s') % state[2]) + _checktype(repo.ui, state[2]) subrev = '' if state[2] == 'hg': subrev = "0" * 40 diff --git a/tests/test-audit-subrepo.t b/tests/test-audit-subrepo.t new file mode 100644 --- /dev/null +++ b/tests/test-audit-subrepo.t @@ -0,0 +1,132 @@ +Test illegal name +----------------- + +on commit: + + $ hg init hgname + $ cd hgname + $ mkdir sub + $ hg init sub/.hg + $ echo 'sub/.hg = sub/.hg' >> .hgsub + $ hg ci -qAm 'add subrepo "sub/.hg"' + abort: path 'sub/.hg' is inside nested repo 'sub' + [255] + +prepare tampered repo (including the commit above): + + $ hg import --bypass -qm 'add subrepo "sub/.hg"' - <<'EOF' + > diff --git a/.hgsub b/.hgsub + > new file mode 100644 + > --- /dev/null + > +++ b/.hgsub + > @@ -0,0 +1,1 @@ + > +sub/.hg = sub/.hg + > diff --git a/.hgsubstate b/.hgsubstate + > new file mode 100644 + > --- /dev/null + > +++ b/.hgsubstate + > @@ -0,0 +1,1 @@ + > +0000000000000000000000000000000000000000 sub/.hg + > EOF + $ cd .. + +on clone (and update): + + $ hg clone -q hgname hgname2 + abort: path 'sub/.hg' is inside nested repo 'sub' + [255] + +Test direct symlink traversal +----------------------------- + +#if symlink + +on commit: + + $ mkdir hgsymdir + $ hg init hgsymdir/root + $ cd hgsymdir/root + $ ln -s ../out + $ hg ci -qAm 'add symlink "out"' + $ hg init ../out + $ echo 'out = out' >> .hgsub + $ hg ci -qAm 'add subrepo "out"' + abort: subrepo 'out' traverses symbolic link + [255] + +prepare tampered repo (including the commit above): + + $ hg import --bypass -qm 'add subrepo "out"' - <<'EOF' + > diff --git a/.hgsub b/.hgsub + > new file mode 100644 + > --- /dev/null + > +++ b/.hgsub + > @@ -0,0 +1,1 @@ + > +out = out + > diff --git a/.hgsubstate b/.hgsubstate + > new file mode 100644 + > --- /dev/null + > +++ b/.hgsubstate + > @@ -0,0 +1,1 @@ + > +0000000000000000000000000000000000000000 out + > EOF + $ cd ../.. + +on clone (and update): + + $ mkdir hgsymdir2 + $ hg clone -q hgsymdir/root hgsymdir2/root + abort: subrepo 'out' traverses symbolic link + [255] + $ ls hgsymdir2 + root + +#endif + +Test indirect symlink traversal +------------------------------- + +#if symlink + +on commit: + + $ mkdir hgsymin + $ hg init hgsymin/root + $ cd hgsymin/root + $ ln -s ../out + $ hg ci -qAm 'add symlink "out"' + $ mkdir ../out + $ hg init ../out/sub + $ echo 'out/sub = out/sub' >> .hgsub + $ hg ci -qAm 'add subrepo "out/sub"' + abort: path 'out/sub' traverses symbolic link 'out' + [255] + +prepare tampered repo (including the commit above): + + $ hg import --bypass -qm 'add subrepo "out/sub"' - <<'EOF' + > diff --git a/.hgsub b/.hgsub + > new file mode 100644 + > --- /dev/null + > +++ b/.hgsub + > @@ -0,0 +1,1 @@ + > +out/sub = out/sub + > diff --git a/.hgsubstate b/.hgsubstate + > new file mode 100644 + > --- /dev/null + > +++ b/.hgsubstate + > @@ -0,0 +1,1 @@ + > +0000000000000000000000000000000000000000 out/sub + > EOF + $ cd ../.. + +on clone (and update): + + $ mkdir hgsymin2 + $ hg clone -q hgsymin/root hgsymin2/root + abort: path 'out/sub' traverses symbolic link 'out' + [255] + $ ls hgsymin2 + root + +#endif diff --git a/tests/test-convert-git.t b/tests/test-convert-git.t --- a/tests/test-convert-git.t +++ b/tests/test-convert-git.t @@ -6,6 +6,10 @@ $ echo "autocrlf = false" >> $HOME/.gitconfig $ echo "[extensions]" >> $HGRCPATH $ echo "convert=" >> $HGRCPATH + $ cat >> $HGRCPATH < [subrepos] + > git:allowed = true + > EOF $ GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME $ GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL $ GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0000"; export GIT_AUTHOR_DATE diff --git a/tests/test-mq-subrepo-svn.t b/tests/test-mq-subrepo-svn.t --- a/tests/test-mq-subrepo-svn.t +++ b/tests/test-mq-subrepo-svn.t @@ -5,6 +5,9 @@ > mq = > [diff] > nodates = 1 + > [subrepos] + > allowed = true + > svn:allowed = true > EOF fn to create new repository, and cd into it diff --git a/tests/test-subrepo-git.t b/tests/test-subrepo-git.t --- a/tests/test-subrepo-git.t +++ b/tests/test-subrepo-git.t @@ -41,7 +41,23 @@ add subrepo clone $ echo 's = [git]../gitroot' > .hgsub $ git clone -q ../gitroot s $ hg add .hgsub + +git subrepo is disabled by default + $ hg commit -m 'new git subrepo' + abort: git subrepos not allowed + (see 'hg help config.subrepos' for details) + [255] + +so enable it + + $ cat >> $HGRCPATH < [subrepos] + > git:allowed = true + > EOF + + $ hg commit -m 'new git subrepo' + $ hg debugsub path s source ../gitroot @@ -86,9 +102,29 @@ clone root path s source ../gitroot revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a + $ cd .. + +clone with subrepo disabled (update should fail) + + $ hg clone t -U tc2 --config subrepos.allowed=false + $ hg update -R tc2 --config subrepos.allowed=false + abort: subrepos not enabled + (see 'hg help config.subrepos' for details) + [255] + $ ls tc2 + a + + $ hg clone t tc3 --config subrepos.allowed=false + updating to branch default + abort: subrepos not enabled + (see 'hg help config.subrepos' for details) + [255] + $ ls tc3 + a update to previous substate + $ cd tc $ hg update 1 -q $ cat s/g g @@ -400,11 +436,13 @@ Don't crash if the subrepo is missing Don't crash if subrepo is a broken symlink $ ln -s broken s $ hg status -S + abort: subrepo 's' traverses symbolic link + [255] $ hg push -q - abort: subrepo s is missing (in subrepository "s") + abort: subrepo 's' traverses symbolic link [255] $ hg commit --subrepos -qm missing - abort: subrepo s is missing (in subrepository "s") + abort: subrepo 's' traverses symbolic link [255] $ rm s #endif diff --git a/tests/test-subrepo-svn.t b/tests/test-subrepo-svn.t --- a/tests/test-subrepo-svn.t +++ b/tests/test-subrepo-svn.t @@ -57,6 +57,21 @@ add first svn sub with leading whitespac $ mkdir subdir $ svn co --quiet "$SVNREPOURL"/src subdir/s $ hg add .hgsub + +svn subrepo is disabled by default + + $ hg ci -m1 + abort: svn subrepos not allowed + (see 'hg help config.subrepos' for details) + [255] + +so enable it + + $ cat >> $HGRCPATH < [subrepos] + > svn:allowed = true + > EOF + $ hg ci -m1 make sure we avoid empty commits (issue2445) diff --git a/tests/test-subrepo.t b/tests/test-subrepo.t --- a/tests/test-subrepo.t +++ b/tests/test-subrepo.t @@ -484,9 +484,47 @@ clone path t source t revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e + $ cd .. + +clone with subrepo disabled (update should fail) + + $ hg clone t -U tc2 --config subrepos.allowed=false + $ hg update -R tc2 --config subrepos.allowed=false + abort: subrepos not enabled + (see 'hg help config.subrepos' for details) + [255] + $ ls tc2 + a + + $ hg clone t tc3 --config subrepos.allowed=false + updating to branch default + abort: subrepos not enabled + (see 'hg help config.subrepos' for details) + [255] + $ ls tc3 + a + +And again with just the hg type disabled + + $ hg clone t -U tc4 --config subrepos.hg:allowed=false + $ hg update -R tc4 --config subrepos.hg:allowed=false + abort: hg subrepos not allowed + (see 'hg help config.subrepos' for details) + [255] + $ ls tc4 + a + + $ hg clone t tc5 --config subrepos.hg:allowed=false + updating to branch default + abort: hg subrepos not allowed + (see 'hg help config.subrepos' for details) + [255] + $ ls tc5 + a push + $ cd tc $ echo bah > t/t $ hg ci -m11 committing subrepository t