Show More
@@ -0,0 +1,15 b'' | |||||
|
1 | Test for CVE-2016-3630 | |||
|
2 | ||||
|
3 | $ hg init | |||
|
4 | ||||
|
5 | >>> open("a.i", "w").write( | |||
|
6 | ... """eJxjYGZgZIAAYQYGxhgom+k/FMx8YKx9ZUaKSOyqo4cnuKb8mbqHV5cBCVTMWb1Cwqkhe4Gsg9AD | |||
|
7 | ... Joa3dYtcYYYBAQ8Qr4OqZAYRICPTSr5WKd/42rV36d+8/VmrNpv7NP1jQAXrQE4BqQUARngwVA==""" | |||
|
8 | ... .decode("base64").decode("zlib")) | |||
|
9 | ||||
|
10 | $ hg debugindex a.i | |||
|
11 | rev offset length delta linkrev nodeid p1 p2 | |||
|
12 | 0 0 19 -1 2 99e0332bd498 000000000000 000000000000 | |||
|
13 | 1 19 12 0 3 6674f57a23d8 99e0332bd498 000000000000 | |||
|
14 | $ hg debugdata a.i 1 2>&1 | grep decoded | |||
|
15 | mpatch.mpatchError: patch cannot be decoded |
@@ -122,3 +122,4 b' 158bdc8965720ca4061f8f8d806563cfc7cdb62e' | |||||
122 | 2408645de650d8a29a6ce9e7dce601d8dd0d1474 0 iQIVAwUAVq/xFSBXgaxoKi1yAQLsxhAAg+E6uJCtZZOugrrFi9S6C20SRPBwHwmw22PC5z3Ufp9Vf3vqSL/+zmWI9d/yezIVcTXgM9rKCvq58sZvo4FuO2ngPx7bL9LMJ3qx0IyHUKjwa3AwrzjSzvVhNIrRoimD+lVBI/GLmoszpMICM+Nyg3D41fNJKs6YpnwwsHNJkjMwz0n2SHAShWAgIilyANNVnwnzHE68AIkB/gBkUGtrjf6xB9mXQxAv4GPco/234FAkX9xSWsM0Rx+JLLrSBXoHmIlmu9LPjC0AKn8/DDke+fj7bFaF7hdJBUYOtlYH6f7NIvyZSpw0FHl7jPxoRCtXzIV+1dZEbbIMIXzNtzPFVDYDfMhLqpTgthkZ9x0UaMaHecCUWYYBp8G/IyVS40GJodl8xnRiXUkFejbK/NDdR1f9iZS0dtiFu66cATMdb6d+MG+zW0nDKiQmBt6bwynysqn4g3SIGQFEPyEoRy0bXiefHrlkeHbdfc4zgoejx3ywcRDMGvUbpWs5C43EPu44irKXcqC695vAny3A7nZpt/XP5meDdOF67DNQPvhFdjPPbJBpSsUi2hUlZ+599wUfr3lNVzeEzHT7XApTOf6ysuGtHH3qcVHpFqQSRL1MI0f2xL13UadgTVWYrnHEis7f+ncwlWiR0ucpJB3+dQQh3NVGVo89MfbIZPkA8iil03U= |
|
122 | 2408645de650d8a29a6ce9e7dce601d8dd0d1474 0 iQIVAwUAVq/xFSBXgaxoKi1yAQLsxhAAg+E6uJCtZZOugrrFi9S6C20SRPBwHwmw22PC5z3Ufp9Vf3vqSL/+zmWI9d/yezIVcTXgM9rKCvq58sZvo4FuO2ngPx7bL9LMJ3qx0IyHUKjwa3AwrzjSzvVhNIrRoimD+lVBI/GLmoszpMICM+Nyg3D41fNJKs6YpnwwsHNJkjMwz0n2SHAShWAgIilyANNVnwnzHE68AIkB/gBkUGtrjf6xB9mXQxAv4GPco/234FAkX9xSWsM0Rx+JLLrSBXoHmIlmu9LPjC0AKn8/DDke+fj7bFaF7hdJBUYOtlYH6f7NIvyZSpw0FHl7jPxoRCtXzIV+1dZEbbIMIXzNtzPFVDYDfMhLqpTgthkZ9x0UaMaHecCUWYYBp8G/IyVS40GJodl8xnRiXUkFejbK/NDdR1f9iZS0dtiFu66cATMdb6d+MG+zW0nDKiQmBt6bwynysqn4g3SIGQFEPyEoRy0bXiefHrlkeHbdfc4zgoejx3ywcRDMGvUbpWs5C43EPu44irKXcqC695vAny3A7nZpt/XP5meDdOF67DNQPvhFdjPPbJBpSsUi2hUlZ+599wUfr3lNVzeEzHT7XApTOf6ysuGtHH3qcVHpFqQSRL1MI0f2xL13UadgTVWYrnHEis7f+ncwlWiR0ucpJB3+dQQh3NVGVo89MfbIZPkA8iil03U= | |
123 | b698abf971e7377d9b7ec7fc8c52df45255b0329 0 iQIVAwUAVrJ4YCBXgaxoKi1yAQJsKw/+JHSR0bIyarO4/VilFwsYxCprOnPxmUdS4qc4yjvpbf7Dqqr/OnOHJA29LrMoqWqsHgREepemjqiNindwNtlZec+KgmbF08ihSBBpls96UTTYTcytKRkkbrB+FhwB0iDl/o8RgGPniyG6M7gOp6p8pXQVRCOToIY1B/G0rtpkcU1N3GbiZntO5Fm/LPAVIE74VaDsamMopQ/wEB8qiERngX/M8SjO1ZSaVNW6KjRUsarLXQB9ziVJBolK/WnQsDwEeuWU2udpjBiOHnFC6h84uBpc8rLGhr419bKMJcjgl+0sl2zHGPY2edQYuJqVjVENzf4zzZA+xPgKw3GrSTpd37PEnGU/fufdJ0X+pp3kvmO1cV3TsvVMTCn7NvS6+w8SGdHdwKQQwelYI6vmJnjuOCATbafJiHMaOQ0GVYYk6PPoGrYcQ081x6dStCMaHIPOV1Wirwd2wq+SN9Ql8H6njftBf5Sa5tVWdW/zrhsltMsdZYZagZ/oFT3t83exL0rgZ96bZFs0j3HO3APELygIVuQ6ybPsFyToMDbURNDvr7ZqPKhQkkdHIUMqEez5ReuVgpbO9CWV/yWpB1/ZCpjNBZyDvw05kG2mOoC7AbHc8aLUS/8DetAmhwyb48LW4qjfUkO7RyxVSxqdnaBOMlsg1wsP2S+SlkZKsDHjcquZJ5U= |
|
123 | b698abf971e7377d9b7ec7fc8c52df45255b0329 0 iQIVAwUAVrJ4YCBXgaxoKi1yAQJsKw/+JHSR0bIyarO4/VilFwsYxCprOnPxmUdS4qc4yjvpbf7Dqqr/OnOHJA29LrMoqWqsHgREepemjqiNindwNtlZec+KgmbF08ihSBBpls96UTTYTcytKRkkbrB+FhwB0iDl/o8RgGPniyG6M7gOp6p8pXQVRCOToIY1B/G0rtpkcU1N3GbiZntO5Fm/LPAVIE74VaDsamMopQ/wEB8qiERngX/M8SjO1ZSaVNW6KjRUsarLXQB9ziVJBolK/WnQsDwEeuWU2udpjBiOHnFC6h84uBpc8rLGhr419bKMJcjgl+0sl2zHGPY2edQYuJqVjVENzf4zzZA+xPgKw3GrSTpd37PEnGU/fufdJ0X+pp3kvmO1cV3TsvVMTCn7NvS6+w8SGdHdwKQQwelYI6vmJnjuOCATbafJiHMaOQ0GVYYk6PPoGrYcQ081x6dStCMaHIPOV1Wirwd2wq+SN9Ql8H6njftBf5Sa5tVWdW/zrhsltMsdZYZagZ/oFT3t83exL0rgZ96bZFs0j3HO3APELygIVuQ6ybPsFyToMDbURNDvr7ZqPKhQkkdHIUMqEez5ReuVgpbO9CWV/yWpB1/ZCpjNBZyDvw05kG2mOoC7AbHc8aLUS/8DetAmhwyb48LW4qjfUkO7RyxVSxqdnaBOMlsg1wsP2S+SlkZKsDHjcquZJ5U= | |
124 | d493d64757eb45ada99fcb3693e479a51b7782da 0 iQIVAwUAVtYt4SBXgaxoKi1yAQL6TQ/9FzYE/xOSC2LYqPdPjCXNjGuZdN1WMf/8fUMYT83NNOoLEBGx37C0bAxgD4/P03FwYMuP37IjIcX8vN6fWvtG9Oo0o2n/oR3SKjpsheh2zxhAFX3vXhFD4U18wCz/DnM0O1qGJwJ49kk/99WNgDWeW4n9dMzTFpcaeZBCu1REbZQS40Z+ArXTDCr60g5TLN1XR1WKEzQJvF71rvaE6P8d3GLoGobTIJMLi5UnMwGsnsv2/EIPrWHQiAY9ZEnYq6deU/4RMh9c7afZie9I+ycIA/qVH6vXNt3/a2BP3Frmv8IvKPzqwnoWmIUamew9lLf1joD5joBy8Yu+qMW0/s6DYUGQ4Slk9qIfn6wh4ySgT/7FJUMcayx9ONDq7920RjRc+XFpD8B3Zhj2mM+0g9At1FgX2w2Gkf957oz2nlgTVh9sdPvP6UvWzhqszPMpdG5Vt0oc5vuyobW333qSkufCxi5gmH7do1DIzErMcy8b6IpZUDeQ/dakKwLQpZVVPF15IrNa/zsOW55SrGrL8/ErM/mXNQBBAqvRsOLq2njFqK2JaoG6biH21DMjHVZFw2wBRoLQxbOppfz2/e3mNkNy9HjgJTW3+0iHWvRzMSjwRbk9BlbkmH6kG5163ElHq3Ft3uuQyZBL9I5SQxlHi9s/CV0YSTYthpWR3ChKIMoqBQ0= |
|
124 | d493d64757eb45ada99fcb3693e479a51b7782da 0 iQIVAwUAVtYt4SBXgaxoKi1yAQL6TQ/9FzYE/xOSC2LYqPdPjCXNjGuZdN1WMf/8fUMYT83NNOoLEBGx37C0bAxgD4/P03FwYMuP37IjIcX8vN6fWvtG9Oo0o2n/oR3SKjpsheh2zxhAFX3vXhFD4U18wCz/DnM0O1qGJwJ49kk/99WNgDWeW4n9dMzTFpcaeZBCu1REbZQS40Z+ArXTDCr60g5TLN1XR1WKEzQJvF71rvaE6P8d3GLoGobTIJMLi5UnMwGsnsv2/EIPrWHQiAY9ZEnYq6deU/4RMh9c7afZie9I+ycIA/qVH6vXNt3/a2BP3Frmv8IvKPzqwnoWmIUamew9lLf1joD5joBy8Yu+qMW0/s6DYUGQ4Slk9qIfn6wh4ySgT/7FJUMcayx9ONDq7920RjRc+XFpD8B3Zhj2mM+0g9At1FgX2w2Gkf957oz2nlgTVh9sdPvP6UvWzhqszPMpdG5Vt0oc5vuyobW333qSkufCxi5gmH7do1DIzErMcy8b6IpZUDeQ/dakKwLQpZVVPF15IrNa/zsOW55SrGrL8/ErM/mXNQBBAqvRsOLq2njFqK2JaoG6biH21DMjHVZFw2wBRoLQxbOppfz2/e3mNkNy9HjgJTW3+0iHWvRzMSjwRbk9BlbkmH6kG5163ElHq3Ft3uuQyZBL9I5SQxlHi9s/CV0YSTYthpWR3ChKIMoqBQ0= | |
|
125 | ae279d4a19e9683214cbd1fe8298cf0b50571432 0 iQIVAwUAVvqzViBXgaxoKi1yAQKUCxAAtctMD3ydbe+li3iYjhY5qT0wyHwPr9fcLqsQUJ4ZtD4sK3oxCRZFWFxNBk5bIIyiwusSEJPiPddoQ7NljSZlYDI0HR3R4vns55fmDwPG07Ykf7aSyqr+c2ppCGzn2/2ID476FNtzKqjF+LkVyadgI9vgZk5S4BgdSlfSRBL+1KtB1BlF5etIZnc5U9qs1uqzZJc06xyyF8HlrmMZkAvRUbsx/JzA5LgzZ2WzueaxZgYzYjDk0nPLgyPPBj0DVyWXnW/kdRNmKHNbaZ9aZlWmdPCEoq5iBm71d7Xoa61shmeuVZWvxHNqXdjVMHVeT61cRxjdfxTIkJwvlRGwpy7V17vTgzWFxw6QJpmr7kupRo3idsDydLDPHGUsxP3uMZFsp6+4rEe6qbafjNajkRyiw7kVGCxboOFN0rLVJPZwZGksEIkw58IHcPhZNT1bHHocWOA/uHJTAynfKsAdv/LDdGKcZWUCFOzlokw54xbPvdrBtEOnYNp15OY01IAJd2FCUki5WHvhELUggTjfank1Tc3/Rt1KrGOFhg80CWq6eMiuiWkHGvYq3fjNLbgjl3JJatUFoB+cX1ulDOGsLJEXQ4v5DNHgel0o2H395owNlStksSeW1UBVk0hUK/ADtVUYKAPEIFiboh1iDpEOl40JVnYdsGz3w5FLj2w+16/1vWs= |
@@ -135,3 +135,4 b' 158bdc8965720ca4061f8f8d806563cfc7cdb62e' | |||||
135 | 2408645de650d8a29a6ce9e7dce601d8dd0d1474 3.7 |
|
135 | 2408645de650d8a29a6ce9e7dce601d8dd0d1474 3.7 | |
136 | b698abf971e7377d9b7ec7fc8c52df45255b0329 3.7.1 |
|
136 | b698abf971e7377d9b7ec7fc8c52df45255b0329 3.7.1 | |
137 | d493d64757eb45ada99fcb3693e479a51b7782da 3.7.2 |
|
137 | d493d64757eb45ada99fcb3693e479a51b7782da 3.7.2 | |
|
138 | ae279d4a19e9683214cbd1fe8298cf0b50571432 3.7.3 |
@@ -352,6 +352,9 b' class commandline(object):' | |||||
352 | def _run2(self, cmd, *args, **kwargs): |
|
352 | def _run2(self, cmd, *args, **kwargs): | |
353 | return self._dorun(util.popen2, cmd, *args, **kwargs) |
|
353 | return self._dorun(util.popen2, cmd, *args, **kwargs) | |
354 |
|
354 | |||
|
355 | def _run3(self, cmd, *args, **kwargs): | |||
|
356 | return self._dorun(util.popen3, cmd, *args, **kwargs) | |||
|
357 | ||||
355 | def _dorun(self, openfunc, cmd, *args, **kwargs): |
|
358 | def _dorun(self, openfunc, cmd, *args, **kwargs): | |
356 | cmdline = self._cmdline(cmd, *args, **kwargs) |
|
359 | cmdline = self._cmdline(cmd, *args, **kwargs) | |
357 | self.ui.debug('running: %s\n' % (cmdline,)) |
|
360 | self.ui.debug('running: %s\n' % (cmdline,)) |
@@ -32,61 +32,28 b' class submodule(object):' | |||||
32 | def hgsubstate(self): |
|
32 | def hgsubstate(self): | |
33 | return "%s %s" % (self.node, self.path) |
|
33 | return "%s %s" % (self.node, self.path) | |
34 |
|
34 | |||
35 | class convert_git(common.converter_source): |
|
35 | class convert_git(common.converter_source, common.commandline): | |
36 | # Windows does not support GIT_DIR= construct while other systems |
|
36 | # Windows does not support GIT_DIR= construct while other systems | |
37 | # cannot remove environment variable. Just assume none have |
|
37 | # cannot remove environment variable. Just assume none have | |
38 | # both issues. |
|
38 | # both issues. | |
39 | if util.safehasattr(os, 'unsetenv'): |
|
39 | ||
40 | def gitopen(self, s, err=None): |
|
40 | def _gitcmd(self, cmd, *args, **kwargs): | |
41 | prevgitdir = os.environ.get('GIT_DIR') |
|
41 | return cmd('--git-dir=%s' % self.path, *args, **kwargs) | |
42 | os.environ['GIT_DIR'] = self.path |
|
42 | ||
43 | try: |
|
43 | def gitrun0(self, *args, **kwargs): | |
44 | if err == subprocess.PIPE: |
|
44 | return self._gitcmd(self.run0, *args, **kwargs) | |
45 | (stdin, stdout, stderr) = util.popen3(s) |
|
|||
46 | return stdout |
|
|||
47 | elif err == subprocess.STDOUT: |
|
|||
48 | return self.popen_with_stderr(s) |
|
|||
49 | else: |
|
|||
50 | return util.popen(s, 'rb') |
|
|||
51 | finally: |
|
|||
52 | if prevgitdir is None: |
|
|||
53 | del os.environ['GIT_DIR'] |
|
|||
54 | else: |
|
|||
55 | os.environ['GIT_DIR'] = prevgitdir |
|
|||
56 |
|
45 | |||
57 |
|
|
46 | def gitrun(self, *args, **kwargs): | |
58 | prevgitdir = os.environ.get('GIT_DIR') |
|
47 | return self._gitcmd(self.run, *args, **kwargs) | |
59 | os.environ['GIT_DIR'] = self.path |
|
48 | ||
60 | try: |
|
49 | def gitrunlines0(self, *args, **kwargs): | |
61 | return util.popen3(s) |
|
50 | return self._gitcmd(self.runlines0, *args, **kwargs) | |
62 | finally: |
|
|||
63 | if prevgitdir is None: |
|
|||
64 | del os.environ['GIT_DIR'] |
|
|||
65 | else: |
|
|||
66 | os.environ['GIT_DIR'] = prevgitdir |
|
|||
67 |
|
51 | |||
68 | else: |
|
52 | def gitrunlines(self, *args, **kwargs): | |
69 | def gitopen(self, s, err=None): |
|
53 | return self._gitcmd(self.runlines, *args, **kwargs) | |
70 | if err == subprocess.PIPE: |
|
|||
71 | (sin, so, se) = util.popen3('GIT_DIR=%s %s' % (self.path, s)) |
|
|||
72 | return so |
|
|||
73 | elif err == subprocess.STDOUT: |
|
|||
74 | return self.popen_with_stderr(s) |
|
|||
75 | else: |
|
|||
76 | return util.popen('GIT_DIR=%s %s' % (self.path, s), 'rb') |
|
|||
77 |
|
54 | |||
78 |
|
|
55 | def gitpipe(self, *args, **kwargs): | |
79 | return util.popen3('GIT_DIR=%s %s' % (self.path, s)) |
|
56 | return self._gitcmd(self._run3, *args, **kwargs) | |
80 |
|
||||
81 | def popen_with_stderr(self, s): |
|
|||
82 | p = subprocess.Popen(s, shell=True, bufsize=-1, |
|
|||
83 | close_fds=util.closefds, |
|
|||
84 | stdin=subprocess.PIPE, |
|
|||
85 | stdout=subprocess.PIPE, |
|
|||
86 | stderr=subprocess.STDOUT, |
|
|||
87 | universal_newlines=False, |
|
|||
88 | env=None) |
|
|||
89 | return p.stdout |
|
|||
90 |
|
57 | |||
91 | def gitread(self, s): |
|
58 | def gitread(self, s): | |
92 | fh = self.gitopen(s) |
|
59 | fh = self.gitopen(s) | |
@@ -95,6 +62,7 b' class convert_git(common.converter_sourc' | |||||
95 |
|
62 | |||
96 | def __init__(self, ui, path, revs=None): |
|
63 | def __init__(self, ui, path, revs=None): | |
97 | super(convert_git, self).__init__(ui, path, revs=revs) |
|
64 | super(convert_git, self).__init__(ui, path, revs=revs) | |
|
65 | common.commandline.__init__(self, ui, 'git') | |||
98 |
|
66 | |||
99 | if os.path.isdir(path + "/.git"): |
|
67 | if os.path.isdir(path + "/.git"): | |
100 | path += "/.git" |
|
68 | path += "/.git" | |
@@ -107,20 +75,20 b' class convert_git(common.converter_sourc' | |||||
107 | if similarity < 0 or similarity > 100: |
|
75 | if similarity < 0 or similarity > 100: | |
108 | raise error.Abort(_('similarity must be between 0 and 100')) |
|
76 | raise error.Abort(_('similarity must be between 0 and 100')) | |
109 | if similarity > 0: |
|
77 | if similarity > 0: | |
110 | self.simopt = '-C%d%%' % similarity |
|
78 | self.simopt = ['-C%d%%' % similarity] | |
111 | findcopiesharder = ui.configbool('convert', 'git.findcopiesharder', |
|
79 | findcopiesharder = ui.configbool('convert', 'git.findcopiesharder', | |
112 | False) |
|
80 | False) | |
113 | if findcopiesharder: |
|
81 | if findcopiesharder: | |
114 |
self.simopt |
|
82 | self.simopt.append('--find-copies-harder') | |
115 | else: |
|
83 | else: | |
116 |
self.simopt = |
|
84 | self.simopt = [] | |
117 |
|
85 | |||
118 | common.checktool('git', 'git') |
|
86 | common.checktool('git', 'git') | |
119 |
|
87 | |||
120 | self.path = path |
|
88 | self.path = path | |
121 | self.submodules = [] |
|
89 | self.submodules = [] | |
122 |
|
90 | |||
123 |
self.catfilepipe = self.gitpipe(' |
|
91 | self.catfilepipe = self.gitpipe('cat-file', '--batch') | |
124 |
|
92 | |||
125 | def after(self): |
|
93 | def after(self): | |
126 | for f in self.catfilepipe: |
|
94 | for f in self.catfilepipe: | |
@@ -128,14 +96,14 b' class convert_git(common.converter_sourc' | |||||
128 |
|
96 | |||
129 | def getheads(self): |
|
97 | def getheads(self): | |
130 | if not self.revs: |
|
98 | if not self.revs: | |
131 |
|
|
99 | output, status = self.gitrun('rev-parse', '--branches', '--remotes') | |
132 |
heads = |
|
100 | heads = output.splitlines() | |
133 |
if |
|
101 | if status: | |
134 | raise error.Abort(_('cannot retrieve git heads')) |
|
102 | raise error.Abort(_('cannot retrieve git heads')) | |
135 | else: |
|
103 | else: | |
136 | heads = [] |
|
104 | heads = [] | |
137 | for rev in self.revs: |
|
105 | for rev in self.revs: | |
138 |
rawhead, ret = self.gitr |
|
106 | rawhead, ret = self.gitrun('rev-parse', '--verify', rev) | |
139 | heads.append(rawhead[:-1]) |
|
107 | heads.append(rawhead[:-1]) | |
140 | if ret: |
|
108 | if ret: | |
141 | raise error.Abort(_('cannot retrieve git head "%s"') % rev) |
|
109 | raise error.Abort(_('cannot retrieve git head "%s"') % rev) | |
@@ -195,7 +163,7 b' class convert_git(common.converter_sourc' | |||||
195 | self.submodules.append(submodule(s['path'], '', s['url'])) |
|
163 | self.submodules.append(submodule(s['path'], '', s['url'])) | |
196 |
|
164 | |||
197 | def retrievegitmodules(self, version): |
|
165 | def retrievegitmodules(self, version): | |
198 |
modules, ret = self.gitr |
|
166 | modules, ret = self.gitrun('show', '%s:%s' % (version, '.gitmodules')) | |
199 | if ret: |
|
167 | if ret: | |
200 | # This can happen if a file is in the repo that has permissions |
|
168 | # This can happen if a file is in the repo that has permissions | |
201 | # 160000, but there is no .gitmodules file. |
|
169 | # 160000, but there is no .gitmodules file. | |
@@ -211,7 +179,7 b' class convert_git(common.converter_sourc' | |||||
211 | return |
|
179 | return | |
212 |
|
180 | |||
213 | for m in self.submodules: |
|
181 | for m in self.submodules: | |
214 |
node, ret = self.gitr |
|
182 | node, ret = self.gitrun('rev-parse', '%s:%s' % (version, m.path)) | |
215 | if ret: |
|
183 | if ret: | |
216 | continue |
|
184 | continue | |
217 | m.node = node.strip() |
|
185 | m.node = node.strip() | |
@@ -220,15 +188,17 b' class convert_git(common.converter_sourc' | |||||
220 | if full: |
|
188 | if full: | |
221 | raise error.Abort(_("convert from git does not support --full")) |
|
189 | raise error.Abort(_("convert from git does not support --full")) | |
222 | self.modecache = {} |
|
190 | self.modecache = {} | |
223 | fh = self.gitopen("git diff-tree -z --root -m -r %s %s" % ( |
|
191 | cmd = ['diff-tree','-z', '--root', '-m', '-r'] + self.simopt + [version] | |
224 | self.simopt, version)) |
|
192 | output, status = self.gitrun(*cmd) | |
|
193 | if status: | |||
|
194 | raise error.Abort(_('cannot read changes in %s') % version) | |||
225 | changes = [] |
|
195 | changes = [] | |
226 | copies = {} |
|
196 | copies = {} | |
227 | seen = set() |
|
197 | seen = set() | |
228 | entry = None |
|
198 | entry = None | |
229 | subexists = [False] |
|
199 | subexists = [False] | |
230 | subdeleted = [False] |
|
200 | subdeleted = [False] | |
231 |
difftree = |
|
201 | difftree = output.split('\x00') | |
232 | lcount = len(difftree) |
|
202 | lcount = len(difftree) | |
233 | i = 0 |
|
203 | i = 0 | |
234 |
|
204 | |||
@@ -290,8 +260,6 b' class convert_git(common.converter_sourc' | |||||
290 | if f != '.gitmodules' and fdest != '.gitmodules': |
|
260 | if f != '.gitmodules' and fdest != '.gitmodules': | |
291 | copies[fdest] = f |
|
261 | copies[fdest] = f | |
292 | entry = None |
|
262 | entry = None | |
293 | if fh.close(): |
|
|||
294 | raise error.Abort(_('cannot read changes in %s') % version) |
|
|||
295 |
|
263 | |||
296 | if subexists[0]: |
|
264 | if subexists[0]: | |
297 | if subdeleted[0]: |
|
265 | if subdeleted[0]: | |
@@ -338,17 +306,23 b' class convert_git(common.converter_sourc' | |||||
338 | return c |
|
306 | return c | |
339 |
|
307 | |||
340 | def numcommits(self): |
|
308 | def numcommits(self): | |
341 |
|
|
309 | output, ret = self.gitrunlines('rev-list', '--all') | |
|
310 | if ret: | |||
|
311 | raise error.Abort(_('cannot retrieve number of commits in %s') \ | |||
|
312 | % self.path) | |||
|
313 | return len(output) | |||
342 |
|
314 | |||
343 | def gettags(self): |
|
315 | def gettags(self): | |
344 | tags = {} |
|
316 | tags = {} | |
345 | alltags = {} |
|
317 | alltags = {} | |
346 |
|
|
318 | output, status = self.gitrunlines('ls-remote', '--tags', self.path) | |
347 | err=subprocess.STDOUT) |
|
319 | ||
|
320 | if status: | |||
|
321 | raise error.Abort(_('cannot read tags from %s') % self.path) | |||
348 | prefix = 'refs/tags/' |
|
322 | prefix = 'refs/tags/' | |
349 |
|
323 | |||
350 | # Build complete list of tags, both annotated and bare ones |
|
324 | # Build complete list of tags, both annotated and bare ones | |
351 |
for line in |
|
325 | for line in output: | |
352 | line = line.strip() |
|
326 | line = line.strip() | |
353 | if line.startswith("error:") or line.startswith("fatal:"): |
|
327 | if line.startswith("error:") or line.startswith("fatal:"): | |
354 | raise error.Abort(_('cannot read tags from %s') % self.path) |
|
328 | raise error.Abort(_('cannot read tags from %s') % self.path) | |
@@ -356,8 +330,6 b' class convert_git(common.converter_sourc' | |||||
356 | if not tag.startswith(prefix): |
|
330 | if not tag.startswith(prefix): | |
357 | continue |
|
331 | continue | |
358 | alltags[tag[len(prefix):]] = node |
|
332 | alltags[tag[len(prefix):]] = node | |
359 | if fh.close(): |
|
|||
360 | raise error.Abort(_('cannot read tags from %s') % self.path) |
|
|||
361 |
|
333 | |||
362 | # Filter out tag objects for annotated tag refs |
|
334 | # Filter out tag objects for annotated tag refs | |
363 | for tag in alltags: |
|
335 | for tag in alltags: | |
@@ -374,18 +346,20 b' class convert_git(common.converter_sourc' | |||||
374 | def getchangedfiles(self, version, i): |
|
346 | def getchangedfiles(self, version, i): | |
375 | changes = [] |
|
347 | changes = [] | |
376 | if i is None: |
|
348 | if i is None: | |
377 |
|
|
349 | output, status = self.gitrunlines('diff-tree', '--root', '-m', | |
378 | for l in fh: |
|
350 | '-r', version) | |
|
351 | if status: | |||
|
352 | raise error.Abort(_('cannot read changes in %s') % version) | |||
|
353 | for l in output: | |||
379 | if "\t" not in l: |
|
354 | if "\t" not in l: | |
380 | continue |
|
355 | continue | |
381 | m, f = l[:-1].split("\t") |
|
356 | m, f = l[:-1].split("\t") | |
382 | changes.append(f) |
|
357 | changes.append(f) | |
383 | else: |
|
358 | else: | |
384 |
|
|
359 | output, status = self.gitrunlines('diff-tree', '--name-only', | |
385 |
' |
|
360 | '--root', '-r', version, | |
386 | changes = [f.rstrip('\n') for f in fh] |
|
361 | '%s^%s' % (version, i + 1), '--') | |
387 | if fh.close(): |
|
362 | changes = [f.rstrip('\n') for f in output] | |
388 | raise error.Abort(_('cannot read changes in %s') % version) |
|
|||
389 |
|
363 | |||
390 | return changes |
|
364 | return changes | |
391 |
|
365 | |||
@@ -405,8 +379,8 b' class convert_git(common.converter_sourc' | |||||
405 | ]) |
|
379 | ]) | |
406 |
|
380 | |||
407 | try: |
|
381 | try: | |
408 | fh = self.gitopen('git show-ref', err=subprocess.PIPE) |
|
382 | output, status = self.gitrunlines('show-ref') | |
409 |
for line in |
|
383 | for line in output: | |
410 | line = line.strip() |
|
384 | line = line.strip() | |
411 | rev, name = line.split(None, 1) |
|
385 | rev, name = line.split(None, 1) | |
412 | # Process each type of branch |
|
386 | # Process each type of branch |
@@ -205,7 +205,7 b' static struct flist *decode(const char *' | |||||
205 | int pos = 0; |
|
205 | int pos = 0; | |
206 |
|
206 | |||
207 | /* assume worst case size, we won't have many of these lists */ |
|
207 | /* assume worst case size, we won't have many of these lists */ | |
208 | l = lalloc(len / 12); |
|
208 | l = lalloc(len / 12 + 1); | |
209 | if (!l) |
|
209 | if (!l) | |
210 | return NULL; |
|
210 | return NULL; | |
211 |
|
211 | |||
@@ -215,10 +215,10 b' static struct flist *decode(const char *' | |||||
215 | lt->start = getbe32(bin + pos); |
|
215 | lt->start = getbe32(bin + pos); | |
216 | lt->end = getbe32(bin + pos + 4); |
|
216 | lt->end = getbe32(bin + pos + 4); | |
217 | lt->len = getbe32(bin + pos + 8); |
|
217 | lt->len = getbe32(bin + pos + 8); | |
218 | if (lt->start > lt->end) |
|
|||
219 | break; /* sanity check */ |
|
|||
220 | lt->data = bin + pos + 12; |
|
218 | lt->data = bin + pos + 12; | |
221 | pos += 12 + lt->len; |
|
219 | pos += 12 + lt->len; | |
|
220 | if (lt->start > lt->end || lt->len < 0) | |||
|
221 | break; /* sanity check */ | |||
222 | lt++; |
|
222 | lt++; | |
223 | } |
|
223 | } | |
224 |
|
224 |
@@ -1385,6 +1385,11 b' class gitsubrepo(abstractsubrepo):' | |||||
1385 | are not supported and very probably fail. |
|
1385 | are not supported and very probably fail. | |
1386 | """ |
|
1386 | """ | |
1387 | self.ui.debug('%s: git %s\n' % (self._relpath, ' '.join(commands))) |
|
1387 | self.ui.debug('%s: git %s\n' % (self._relpath, ' '.join(commands))) | |
|
1388 | if env is None: | |||
|
1389 | env = os.environ.copy() | |||
|
1390 | # fix for Git CVE-2015-7545 | |||
|
1391 | if 'GIT_ALLOW_PROTOCOL' not in env: | |||
|
1392 | env['GIT_ALLOW_PROTOCOL'] = 'file:git:http:https:ssh' | |||
1388 | # unless ui.quiet is set, print git's stderr, |
|
1393 | # unless ui.quiet is set, print git's stderr, | |
1389 | # which is mostly progress and useful info |
|
1394 | # which is mostly progress and useful info | |
1390 | errpipe = None |
|
1395 | errpipe = None |
@@ -714,7 +714,7 b' damage git repository by renaming a comm' | |||||
714 | $ COMMIT_OBJ=1c/0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd |
|
714 | $ COMMIT_OBJ=1c/0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd | |
715 | $ mv git-repo4/.git/objects/$COMMIT_OBJ git-repo4/.git/objects/$COMMIT_OBJ.tmp |
|
715 | $ mv git-repo4/.git/objects/$COMMIT_OBJ git-repo4/.git/objects/$COMMIT_OBJ.tmp | |
716 | $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:' |
|
716 | $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:' | |
717 |
abort: cannot re |
|
717 | abort: cannot retrieve number of commits in git-repo4/.git | |
718 | $ mv git-repo4/.git/objects/$COMMIT_OBJ.tmp git-repo4/.git/objects/$COMMIT_OBJ |
|
718 | $ mv git-repo4/.git/objects/$COMMIT_OBJ.tmp git-repo4/.git/objects/$COMMIT_OBJ | |
719 | damage git repository by renaming a blob object |
|
719 | damage git repository by renaming a blob object | |
720 |
|
720 | |||
@@ -729,3 +729,20 b' damage git repository by renaming a tree' | |||||
729 | $ mv git-repo4/.git/objects/$TREE_OBJ git-repo4/.git/objects/$TREE_OBJ.tmp |
|
729 | $ mv git-repo4/.git/objects/$TREE_OBJ git-repo4/.git/objects/$TREE_OBJ.tmp | |
730 | $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:' |
|
730 | $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:' | |
731 | abort: cannot read changes in 1c0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd |
|
731 | abort: cannot read changes in 1c0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd | |
|
732 | ||||
|
733 | test for escaping the repo name (CVE-2016-3069) | |||
|
734 | ||||
|
735 | $ git init '`echo pwned >COMMAND-INJECTION`' | |||
|
736 | Initialized empty Git repository in $TESTTMP/`echo pwned >COMMAND-INJECTION`/.git/ | |||
|
737 | $ cd '`echo pwned >COMMAND-INJECTION`' | |||
|
738 | $ git commit -q --allow-empty -m 'empty' | |||
|
739 | $ cd .. | |||
|
740 | $ hg convert '`echo pwned >COMMAND-INJECTION`' 'converted' | |||
|
741 | initializing destination converted repository | |||
|
742 | scanning source... | |||
|
743 | sorting... | |||
|
744 | converting... | |||
|
745 | 0 empty | |||
|
746 | updating bookmarks | |||
|
747 | $ test -f COMMAND-INJECTION | |||
|
748 | [1] |
@@ -1132,4 +1132,36 b' make sure we show changed files, rather ' | |||||
1132 | ? s/foobar.orig |
|
1132 | ? s/foobar.orig | |
1133 | ? s/snake.python.orig |
|
1133 | ? s/snake.python.orig | |
1134 |
|
1134 | |||
|
1135 | test for Git CVE-2016-3068 | |||
|
1136 | $ hg init malicious-subrepository | |||
|
1137 | $ cd malicious-subrepository | |||
|
1138 | $ echo "s = [git]ext::sh -c echo% pwned% >&2" > .hgsub | |||
|
1139 | $ git init s | |||
|
1140 | Initialized empty Git repository in $TESTTMP/tc/malicious-subrepository/s/.git/ | |||
|
1141 | $ cd s | |||
|
1142 | $ git commit --allow-empty -m 'empty' | |||
|
1143 | [master (root-commit) 153f934] empty | |||
1135 | $ cd .. |
|
1144 | $ cd .. | |
|
1145 | $ hg add .hgsub | |||
|
1146 | $ hg commit -m "add subrepo" | |||
|
1147 | $ cd .. | |||
|
1148 | $ env -u GIT_ALLOW_PROTOCOL hg clone malicious-subrepository malicious-subrepository-protected | |||
|
1149 | Cloning into '$TESTTMP/tc/malicious-subrepository-protected/s'... | |||
|
1150 | fatal: transport 'ext' not allowed | |||
|
1151 | updating to branch default | |||
|
1152 | cloning subrepo s from ext::sh -c echo% pwned% >&2 | |||
|
1153 | abort: git clone error 128 in s (in subrepo s) | |||
|
1154 | [255] | |||
|
1155 | ||||
|
1156 | whitelisting of ext should be respected (that's the git submodule behaviour) | |||
|
1157 | $ env GIT_ALLOW_PROTOCOL=ext hg clone malicious-subrepository malicious-subrepository-clone-allowed | |||
|
1158 | Cloning into '$TESTTMP/tc/malicious-subrepository-clone-allowed/s'... | |||
|
1159 | pwned | |||
|
1160 | fatal: Could not read from remote repository. | |||
|
1161 | ||||
|
1162 | Please make sure you have the correct access rights | |||
|
1163 | and the repository exists. | |||
|
1164 | updating to branch default | |||
|
1165 | cloning subrepo s from ext::sh -c echo% pwned% >&2 | |||
|
1166 | abort: git clone error 128 in s (in subrepo s) | |||
|
1167 | [255] |
General Comments 0
You need to be logged in to leave comments.
Login now