##// END OF EJS Templates
tests: disable test of buffer overflow in parsers.c if --pure...
Yuya Nishihara -
r25859:16195639 stable
parent child Browse files
Show More
@@ -1,378 +1,382 b''
1 import os, stat
1 import os, stat
2 import re
2 import re
3 import socket
3 import socket
4 import sys
4 import sys
5 import tempfile
5 import tempfile
6
6
7 tempprefix = 'hg-hghave-'
7 tempprefix = 'hg-hghave-'
8
8
9 checks = {
9 checks = {
10 "true": (lambda: True, "yak shaving"),
10 "true": (lambda: True, "yak shaving"),
11 "false": (lambda: False, "nail clipper"),
11 "false": (lambda: False, "nail clipper"),
12 }
12 }
13
13
14 def check(name, desc):
14 def check(name, desc):
15 def decorator(func):
15 def decorator(func):
16 checks[name] = (func, desc)
16 checks[name] = (func, desc)
17 return func
17 return func
18 return decorator
18 return decorator
19
19
20 def matchoutput(cmd, regexp, ignorestatus=False):
20 def matchoutput(cmd, regexp, ignorestatus=False):
21 """Return True if cmd executes successfully and its output
21 """Return True if cmd executes successfully and its output
22 is matched by the supplied regular expression.
22 is matched by the supplied regular expression.
23 """
23 """
24 r = re.compile(regexp)
24 r = re.compile(regexp)
25 fh = os.popen(cmd)
25 fh = os.popen(cmd)
26 s = fh.read()
26 s = fh.read()
27 try:
27 try:
28 ret = fh.close()
28 ret = fh.close()
29 except IOError:
29 except IOError:
30 # Happen in Windows test environment
30 # Happen in Windows test environment
31 ret = 1
31 ret = 1
32 return (ignorestatus or ret is None) and r.search(s)
32 return (ignorestatus or ret is None) and r.search(s)
33
33
34 @check("baz", "GNU Arch baz client")
34 @check("baz", "GNU Arch baz client")
35 def has_baz():
35 def has_baz():
36 return matchoutput('baz --version 2>&1', r'baz Bazaar version')
36 return matchoutput('baz --version 2>&1', r'baz Bazaar version')
37
37
38 @check("bzr", "Canonical's Bazaar client")
38 @check("bzr", "Canonical's Bazaar client")
39 def has_bzr():
39 def has_bzr():
40 try:
40 try:
41 import bzrlib
41 import bzrlib
42 return bzrlib.__doc__ is not None
42 return bzrlib.__doc__ is not None
43 except ImportError:
43 except ImportError:
44 return False
44 return False
45
45
46 @check("bzr114", "Canonical's Bazaar client >= 1.14")
46 @check("bzr114", "Canonical's Bazaar client >= 1.14")
47 def has_bzr114():
47 def has_bzr114():
48 try:
48 try:
49 import bzrlib
49 import bzrlib
50 return (bzrlib.__doc__ is not None
50 return (bzrlib.__doc__ is not None
51 and bzrlib.version_info[:2] >= (1, 14))
51 and bzrlib.version_info[:2] >= (1, 14))
52 except ImportError:
52 except ImportError:
53 return False
53 return False
54
54
55 @check("cvs", "cvs client/server")
55 @check("cvs", "cvs client/server")
56 def has_cvs():
56 def has_cvs():
57 re = r'Concurrent Versions System.*?server'
57 re = r'Concurrent Versions System.*?server'
58 return matchoutput('cvs --version 2>&1', re) and not has_msys()
58 return matchoutput('cvs --version 2>&1', re) and not has_msys()
59
59
60 @check("cvs112", "cvs client/server >= 1.12")
60 @check("cvs112", "cvs client/server >= 1.12")
61 def has_cvs112():
61 def has_cvs112():
62 re = r'Concurrent Versions System \(CVS\) 1.12.*?server'
62 re = r'Concurrent Versions System \(CVS\) 1.12.*?server'
63 return matchoutput('cvs --version 2>&1', re) and not has_msys()
63 return matchoutput('cvs --version 2>&1', re) and not has_msys()
64
64
65 @check("darcs", "darcs client")
65 @check("darcs", "darcs client")
66 def has_darcs():
66 def has_darcs():
67 return matchoutput('darcs --version', r'2\.[2-9]', True)
67 return matchoutput('darcs --version', r'2\.[2-9]', True)
68
68
69 @check("mtn", "monotone client (>= 1.0)")
69 @check("mtn", "monotone client (>= 1.0)")
70 def has_mtn():
70 def has_mtn():
71 return matchoutput('mtn --version', r'monotone', True) and not matchoutput(
71 return matchoutput('mtn --version', r'monotone', True) and not matchoutput(
72 'mtn --version', r'monotone 0\.', True)
72 'mtn --version', r'monotone 0\.', True)
73
73
74 @check("eol-in-paths", "end-of-lines in paths")
74 @check("eol-in-paths", "end-of-lines in paths")
75 def has_eol_in_paths():
75 def has_eol_in_paths():
76 try:
76 try:
77 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix, suffix='\n\r')
77 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix, suffix='\n\r')
78 os.close(fd)
78 os.close(fd)
79 os.remove(path)
79 os.remove(path)
80 return True
80 return True
81 except (IOError, OSError):
81 except (IOError, OSError):
82 return False
82 return False
83
83
84 @check("execbit", "executable bit")
84 @check("execbit", "executable bit")
85 def has_executablebit():
85 def has_executablebit():
86 try:
86 try:
87 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
87 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
88 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
88 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
89 try:
89 try:
90 os.close(fh)
90 os.close(fh)
91 m = os.stat(fn).st_mode & 0o777
91 m = os.stat(fn).st_mode & 0o777
92 new_file_has_exec = m & EXECFLAGS
92 new_file_has_exec = m & EXECFLAGS
93 os.chmod(fn, m ^ EXECFLAGS)
93 os.chmod(fn, m ^ EXECFLAGS)
94 exec_flags_cannot_flip = ((os.stat(fn).st_mode & 0o777) == m)
94 exec_flags_cannot_flip = ((os.stat(fn).st_mode & 0o777) == m)
95 finally:
95 finally:
96 os.unlink(fn)
96 os.unlink(fn)
97 except (IOError, OSError):
97 except (IOError, OSError):
98 # we don't care, the user probably won't be able to commit anyway
98 # we don't care, the user probably won't be able to commit anyway
99 return False
99 return False
100 return not (new_file_has_exec or exec_flags_cannot_flip)
100 return not (new_file_has_exec or exec_flags_cannot_flip)
101
101
102 @check("icasefs", "case insensitive file system")
102 @check("icasefs", "case insensitive file system")
103 def has_icasefs():
103 def has_icasefs():
104 # Stolen from mercurial.util
104 # Stolen from mercurial.util
105 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
105 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
106 os.close(fd)
106 os.close(fd)
107 try:
107 try:
108 s1 = os.stat(path)
108 s1 = os.stat(path)
109 d, b = os.path.split(path)
109 d, b = os.path.split(path)
110 p2 = os.path.join(d, b.upper())
110 p2 = os.path.join(d, b.upper())
111 if path == p2:
111 if path == p2:
112 p2 = os.path.join(d, b.lower())
112 p2 = os.path.join(d, b.lower())
113 try:
113 try:
114 s2 = os.stat(p2)
114 s2 = os.stat(p2)
115 return s2 == s1
115 return s2 == s1
116 except OSError:
116 except OSError:
117 return False
117 return False
118 finally:
118 finally:
119 os.remove(path)
119 os.remove(path)
120
120
121 @check("fifo", "named pipes")
121 @check("fifo", "named pipes")
122 def has_fifo():
122 def has_fifo():
123 if getattr(os, "mkfifo", None) is None:
123 if getattr(os, "mkfifo", None) is None:
124 return False
124 return False
125 name = tempfile.mktemp(dir='.', prefix=tempprefix)
125 name = tempfile.mktemp(dir='.', prefix=tempprefix)
126 try:
126 try:
127 os.mkfifo(name)
127 os.mkfifo(name)
128 os.unlink(name)
128 os.unlink(name)
129 return True
129 return True
130 except OSError:
130 except OSError:
131 return False
131 return False
132
132
133 @check("killdaemons", 'killdaemons.py support')
133 @check("killdaemons", 'killdaemons.py support')
134 def has_killdaemons():
134 def has_killdaemons():
135 return True
135 return True
136
136
137 @check("cacheable", "cacheable filesystem")
137 @check("cacheable", "cacheable filesystem")
138 def has_cacheable_fs():
138 def has_cacheable_fs():
139 from mercurial import util
139 from mercurial import util
140
140
141 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
141 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
142 os.close(fd)
142 os.close(fd)
143 try:
143 try:
144 return util.cachestat(path).cacheable()
144 return util.cachestat(path).cacheable()
145 finally:
145 finally:
146 os.remove(path)
146 os.remove(path)
147
147
148 @check("lsprof", "python lsprof module")
148 @check("lsprof", "python lsprof module")
149 def has_lsprof():
149 def has_lsprof():
150 try:
150 try:
151 import _lsprof
151 import _lsprof
152 _lsprof.Profiler # silence unused import warning
152 _lsprof.Profiler # silence unused import warning
153 return True
153 return True
154 except ImportError:
154 except ImportError:
155 return False
155 return False
156
156
157 @check("gettext", "GNU Gettext (msgfmt)")
157 @check("gettext", "GNU Gettext (msgfmt)")
158 def has_gettext():
158 def has_gettext():
159 return matchoutput('msgfmt --version', 'GNU gettext-tools')
159 return matchoutput('msgfmt --version', 'GNU gettext-tools')
160
160
161 @check("git", "git command line client")
161 @check("git", "git command line client")
162 def has_git():
162 def has_git():
163 return matchoutput('git --version 2>&1', r'^git version')
163 return matchoutput('git --version 2>&1', r'^git version')
164
164
165 @check("docutils", "Docutils text processing library")
165 @check("docutils", "Docutils text processing library")
166 def has_docutils():
166 def has_docutils():
167 try:
167 try:
168 from docutils.core import publish_cmdline
168 from docutils.core import publish_cmdline
169 publish_cmdline # silence unused import
169 publish_cmdline # silence unused import
170 return True
170 return True
171 except ImportError:
171 except ImportError:
172 return False
172 return False
173
173
174 def getsvnversion():
174 def getsvnversion():
175 m = matchoutput('svn --version --quiet 2>&1', r'^(\d+)\.(\d+)')
175 m = matchoutput('svn --version --quiet 2>&1', r'^(\d+)\.(\d+)')
176 if not m:
176 if not m:
177 return (0, 0)
177 return (0, 0)
178 return (int(m.group(1)), int(m.group(2)))
178 return (int(m.group(1)), int(m.group(2)))
179
179
180 @check("svn15", "subversion client and admin tools >= 1.5")
180 @check("svn15", "subversion client and admin tools >= 1.5")
181 def has_svn15():
181 def has_svn15():
182 return getsvnversion() >= (1, 5)
182 return getsvnversion() >= (1, 5)
183
183
184 @check("svn13", "subversion client and admin tools >= 1.3")
184 @check("svn13", "subversion client and admin tools >= 1.3")
185 def has_svn13():
185 def has_svn13():
186 return getsvnversion() >= (1, 3)
186 return getsvnversion() >= (1, 3)
187
187
188 @check("svn", "subversion client and admin tools")
188 @check("svn", "subversion client and admin tools")
189 def has_svn():
189 def has_svn():
190 return matchoutput('svn --version 2>&1', r'^svn, version') and \
190 return matchoutput('svn --version 2>&1', r'^svn, version') and \
191 matchoutput('svnadmin --version 2>&1', r'^svnadmin, version')
191 matchoutput('svnadmin --version 2>&1', r'^svnadmin, version')
192
192
193 @check("svn-bindings", "subversion python bindings")
193 @check("svn-bindings", "subversion python bindings")
194 def has_svn_bindings():
194 def has_svn_bindings():
195 try:
195 try:
196 import svn.core
196 import svn.core
197 version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
197 version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
198 if version < (1, 4):
198 if version < (1, 4):
199 return False
199 return False
200 return True
200 return True
201 except ImportError:
201 except ImportError:
202 return False
202 return False
203
203
204 @check("p4", "Perforce server and client")
204 @check("p4", "Perforce server and client")
205 def has_p4():
205 def has_p4():
206 return (matchoutput('p4 -V', r'Rev\. P4/') and
206 return (matchoutput('p4 -V', r'Rev\. P4/') and
207 matchoutput('p4d -V', r'Rev\. P4D/'))
207 matchoutput('p4d -V', r'Rev\. P4D/'))
208
208
209 @check("symlink", "symbolic links")
209 @check("symlink", "symbolic links")
210 def has_symlink():
210 def has_symlink():
211 if getattr(os, "symlink", None) is None:
211 if getattr(os, "symlink", None) is None:
212 return False
212 return False
213 name = tempfile.mktemp(dir='.', prefix=tempprefix)
213 name = tempfile.mktemp(dir='.', prefix=tempprefix)
214 try:
214 try:
215 os.symlink(".", name)
215 os.symlink(".", name)
216 os.unlink(name)
216 os.unlink(name)
217 return True
217 return True
218 except (OSError, AttributeError):
218 except (OSError, AttributeError):
219 return False
219 return False
220
220
221 @check("hardlink", "hardlinks")
221 @check("hardlink", "hardlinks")
222 def has_hardlink():
222 def has_hardlink():
223 from mercurial import util
223 from mercurial import util
224 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
224 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
225 os.close(fh)
225 os.close(fh)
226 name = tempfile.mktemp(dir='.', prefix=tempprefix)
226 name = tempfile.mktemp(dir='.', prefix=tempprefix)
227 try:
227 try:
228 util.oslink(fn, name)
228 util.oslink(fn, name)
229 os.unlink(name)
229 os.unlink(name)
230 return True
230 return True
231 except OSError:
231 except OSError:
232 return False
232 return False
233 finally:
233 finally:
234 os.unlink(fn)
234 os.unlink(fn)
235
235
236 @check("tla", "GNU Arch tla client")
236 @check("tla", "GNU Arch tla client")
237 def has_tla():
237 def has_tla():
238 return matchoutput('tla --version 2>&1', r'The GNU Arch Revision')
238 return matchoutput('tla --version 2>&1', r'The GNU Arch Revision')
239
239
240 @check("gpg", "gpg client")
240 @check("gpg", "gpg client")
241 def has_gpg():
241 def has_gpg():
242 return matchoutput('gpg --version 2>&1', r'GnuPG')
242 return matchoutput('gpg --version 2>&1', r'GnuPG')
243
243
244 @check("unix-permissions", "unix-style permissions")
244 @check("unix-permissions", "unix-style permissions")
245 def has_unix_permissions():
245 def has_unix_permissions():
246 d = tempfile.mkdtemp(dir='.', prefix=tempprefix)
246 d = tempfile.mkdtemp(dir='.', prefix=tempprefix)
247 try:
247 try:
248 fname = os.path.join(d, 'foo')
248 fname = os.path.join(d, 'foo')
249 for umask in (0o77, 0o07, 0o22):
249 for umask in (0o77, 0o07, 0o22):
250 os.umask(umask)
250 os.umask(umask)
251 f = open(fname, 'w')
251 f = open(fname, 'w')
252 f.close()
252 f.close()
253 mode = os.stat(fname).st_mode
253 mode = os.stat(fname).st_mode
254 os.unlink(fname)
254 os.unlink(fname)
255 if mode & 0o777 != ~umask & 0o666:
255 if mode & 0o777 != ~umask & 0o666:
256 return False
256 return False
257 return True
257 return True
258 finally:
258 finally:
259 os.rmdir(d)
259 os.rmdir(d)
260
260
261 @check("unix-socket", "AF_UNIX socket family")
261 @check("unix-socket", "AF_UNIX socket family")
262 def has_unix_socket():
262 def has_unix_socket():
263 return getattr(socket, 'AF_UNIX', None) is not None
263 return getattr(socket, 'AF_UNIX', None) is not None
264
264
265 @check("root", "root permissions")
265 @check("root", "root permissions")
266 def has_root():
266 def has_root():
267 return getattr(os, 'geteuid', None) and os.geteuid() == 0
267 return getattr(os, 'geteuid', None) and os.geteuid() == 0
268
268
269 @check("pyflakes", "Pyflakes python linter")
269 @check("pyflakes", "Pyflakes python linter")
270 def has_pyflakes():
270 def has_pyflakes():
271 return matchoutput("sh -c \"echo 'import re' 2>&1 | pyflakes\"",
271 return matchoutput("sh -c \"echo 'import re' 2>&1 | pyflakes\"",
272 r"<stdin>:1: 're' imported but unused",
272 r"<stdin>:1: 're' imported but unused",
273 True)
273 True)
274
274
275 @check("pygments", "Pygments source highlighting library")
275 @check("pygments", "Pygments source highlighting library")
276 def has_pygments():
276 def has_pygments():
277 try:
277 try:
278 import pygments
278 import pygments
279 pygments.highlight # silence unused import warning
279 pygments.highlight # silence unused import warning
280 return True
280 return True
281 except ImportError:
281 except ImportError:
282 return False
282 return False
283
283
284 @check("json", "some json module available")
284 @check("json", "some json module available")
285 def has_json():
285 def has_json():
286 try:
286 try:
287 import json
287 import json
288 json.dumps
288 json.dumps
289 return True
289 return True
290 except ImportError:
290 except ImportError:
291 try:
291 try:
292 import simplejson as json
292 import simplejson as json
293 json.dumps
293 json.dumps
294 return True
294 return True
295 except ImportError:
295 except ImportError:
296 pass
296 pass
297 return False
297 return False
298
298
299 @check("outer-repo", "outer repo")
299 @check("outer-repo", "outer repo")
300 def has_outer_repo():
300 def has_outer_repo():
301 # failing for other reasons than 'no repo' imply that there is a repo
301 # failing for other reasons than 'no repo' imply that there is a repo
302 return not matchoutput('hg root 2>&1',
302 return not matchoutput('hg root 2>&1',
303 r'abort: no repository found', True)
303 r'abort: no repository found', True)
304
304
305 @check("ssl", ("(python >= 2.6 ssl module and python OpenSSL) "
305 @check("ssl", ("(python >= 2.6 ssl module and python OpenSSL) "
306 "OR python >= 2.7.9 ssl"))
306 "OR python >= 2.7.9 ssl"))
307 def has_ssl():
307 def has_ssl():
308 try:
308 try:
309 import ssl
309 import ssl
310 if getattr(ssl, 'create_default_context', False):
310 if getattr(ssl, 'create_default_context', False):
311 return True
311 return True
312 import OpenSSL
312 import OpenSSL
313 OpenSSL.SSL.Context
313 OpenSSL.SSL.Context
314 return True
314 return True
315 except ImportError:
315 except ImportError:
316 return False
316 return False
317
317
318 @check("sslcontext", "python >= 2.7.9 ssl")
318 @check("sslcontext", "python >= 2.7.9 ssl")
319 def has_sslcontext():
319 def has_sslcontext():
320 try:
320 try:
321 import ssl
321 import ssl
322 ssl.SSLContext
322 ssl.SSLContext
323 return True
323 return True
324 except (ImportError, AttributeError):
324 except (ImportError, AttributeError):
325 return False
325 return False
326
326
327 @check("defaultcacerts", "can verify SSL certs by system's CA certs store")
327 @check("defaultcacerts", "can verify SSL certs by system's CA certs store")
328 def has_defaultcacerts():
328 def has_defaultcacerts():
329 from mercurial import sslutil
329 from mercurial import sslutil
330 return sslutil._defaultcacerts() != '!'
330 return sslutil._defaultcacerts() != '!'
331
331
332 @check("windows", "Windows")
332 @check("windows", "Windows")
333 def has_windows():
333 def has_windows():
334 return os.name == 'nt'
334 return os.name == 'nt'
335
335
336 @check("system-sh", "system() uses sh")
336 @check("system-sh", "system() uses sh")
337 def has_system_sh():
337 def has_system_sh():
338 return os.name != 'nt'
338 return os.name != 'nt'
339
339
340 @check("serve", "platform and python can manage 'hg serve -d'")
340 @check("serve", "platform and python can manage 'hg serve -d'")
341 def has_serve():
341 def has_serve():
342 return os.name != 'nt' # gross approximation
342 return os.name != 'nt' # gross approximation
343
343
344 @check("test-repo", "running tests from repository")
344 @check("test-repo", "running tests from repository")
345 def has_test_repo():
345 def has_test_repo():
346 t = os.environ["TESTDIR"]
346 t = os.environ["TESTDIR"]
347 return os.path.isdir(os.path.join(t, "..", ".hg"))
347 return os.path.isdir(os.path.join(t, "..", ".hg"))
348
348
349 @check("tic", "terminfo compiler and curses module")
349 @check("tic", "terminfo compiler and curses module")
350 def has_tic():
350 def has_tic():
351 try:
351 try:
352 import curses
352 import curses
353 curses.COLOR_BLUE
353 curses.COLOR_BLUE
354 return matchoutput('test -x "`which tic`"', '')
354 return matchoutput('test -x "`which tic`"', '')
355 except ImportError:
355 except ImportError:
356 return False
356 return False
357
357
358 @check("msys", "Windows with MSYS")
358 @check("msys", "Windows with MSYS")
359 def has_msys():
359 def has_msys():
360 return os.getenv('MSYSTEM')
360 return os.getenv('MSYSTEM')
361
361
362 @check("aix", "AIX")
362 @check("aix", "AIX")
363 def has_aix():
363 def has_aix():
364 return sys.platform.startswith("aix")
364 return sys.platform.startswith("aix")
365
365
366 @check("osx", "OS X")
366 @check("osx", "OS X")
367 def has_osx():
367 def has_osx():
368 return sys.platform == 'darwin'
368 return sys.platform == 'darwin'
369
369
370 @check("absimport", "absolute_import in __future__")
370 @check("absimport", "absolute_import in __future__")
371 def has_absimport():
371 def has_absimport():
372 import __future__
372 import __future__
373 from mercurial import util
373 from mercurial import util
374 return util.safehasattr(__future__, "absolute_import")
374 return util.safehasattr(__future__, "absolute_import")
375
375
376 @check("py3k", "running with Python 3.x")
376 @check("py3k", "running with Python 3.x")
377 def has_py3k():
377 def has_py3k():
378 return 3 == sys.version_info[0]
378 return 3 == sys.version_info[0]
379
380 @check("pure", "running with pure Python code")
381 def has_pure():
382 return os.environ.get("HGTEST_RUN_TESTS_PURE") == "--pure"
@@ -1,120 +1,124 b''
1 revlog.parseindex must be able to parse the index file even if
1 revlog.parseindex must be able to parse the index file even if
2 an index entry is split between two 64k blocks. The ideal test
2 an index entry is split between two 64k blocks. The ideal test
3 would be to create an index file with inline data where
3 would be to create an index file with inline data where
4 64k < size < 64k + 64 (64k is the size of the read buffer, 64 is
4 64k < size < 64k + 64 (64k is the size of the read buffer, 64 is
5 the size of an index entry) and with an index entry starting right
5 the size of an index entry) and with an index entry starting right
6 before the 64k block boundary, and try to read it.
6 before the 64k block boundary, and try to read it.
7 We approximate that by reducing the read buffer to 1 byte.
7 We approximate that by reducing the read buffer to 1 byte.
8
8
9 $ hg init a
9 $ hg init a
10 $ cd a
10 $ cd a
11 $ echo abc > foo
11 $ echo abc > foo
12 $ hg add foo
12 $ hg add foo
13 $ hg commit -m 'add foo'
13 $ hg commit -m 'add foo'
14 $ echo >> foo
14 $ echo >> foo
15 $ hg commit -m 'change foo'
15 $ hg commit -m 'change foo'
16 $ hg log -r 0:
16 $ hg log -r 0:
17 changeset: 0:7c31755bf9b5
17 changeset: 0:7c31755bf9b5
18 user: test
18 user: test
19 date: Thu Jan 01 00:00:00 1970 +0000
19 date: Thu Jan 01 00:00:00 1970 +0000
20 summary: add foo
20 summary: add foo
21
21
22 changeset: 1:26333235a41c
22 changeset: 1:26333235a41c
23 tag: tip
23 tag: tip
24 user: test
24 user: test
25 date: Thu Jan 01 00:00:00 1970 +0000
25 date: Thu Jan 01 00:00:00 1970 +0000
26 summary: change foo
26 summary: change foo
27
27
28 $ cat >> test.py << EOF
28 $ cat >> test.py << EOF
29 > from mercurial import changelog, scmutil
29 > from mercurial import changelog, scmutil
30 > from mercurial.node import *
30 > from mercurial.node import *
31 >
31 >
32 > class singlebyteread(object):
32 > class singlebyteread(object):
33 > def __init__(self, real):
33 > def __init__(self, real):
34 > self.real = real
34 > self.real = real
35 >
35 >
36 > def read(self, size=-1):
36 > def read(self, size=-1):
37 > if size == 65536:
37 > if size == 65536:
38 > size = 1
38 > size = 1
39 > return self.real.read(size)
39 > return self.real.read(size)
40 >
40 >
41 > def __getattr__(self, key):
41 > def __getattr__(self, key):
42 > return getattr(self.real, key)
42 > return getattr(self.real, key)
43 >
43 >
44 > def opener(*args):
44 > def opener(*args):
45 > o = scmutil.opener(*args)
45 > o = scmutil.opener(*args)
46 > def wrapper(*a):
46 > def wrapper(*a):
47 > f = o(*a)
47 > f = o(*a)
48 > return singlebyteread(f)
48 > return singlebyteread(f)
49 > return wrapper
49 > return wrapper
50 >
50 >
51 > cl = changelog.changelog(opener('.hg/store'))
51 > cl = changelog.changelog(opener('.hg/store'))
52 > print len(cl), 'revisions:'
52 > print len(cl), 'revisions:'
53 > for r in cl:
53 > for r in cl:
54 > print short(cl.node(r))
54 > print short(cl.node(r))
55 > EOF
55 > EOF
56 $ python test.py
56 $ python test.py
57 2 revisions:
57 2 revisions:
58 7c31755bf9b5
58 7c31755bf9b5
59 26333235a41c
59 26333235a41c
60
60
61 $ cd ..
61 $ cd ..
62
62
63 Test corrupted p1/p2 fields that could cause SEGV at parsers.c:
63 Test corrupted p1/p2 fields that could cause SEGV at parsers.c:
64
64
65 #if no-pure
66
65 $ mkdir invalidparent
67 $ mkdir invalidparent
66 $ cd invalidparent
68 $ cd invalidparent
67
69
68 $ hg clone --pull -q --config phases.publish=False ../a limit
70 $ hg clone --pull -q --config phases.publish=False ../a limit
69 $ hg clone --pull -q --config phases.publish=False ../a segv
71 $ hg clone --pull -q --config phases.publish=False ../a segv
70 $ rm -R limit/.hg/cache segv/.hg/cache
72 $ rm -R limit/.hg/cache segv/.hg/cache
71
73
72 $ python <<EOF
74 $ python <<EOF
73 > data = open("limit/.hg/store/00changelog.i", "rb").read()
75 > data = open("limit/.hg/store/00changelog.i", "rb").read()
74 > for n, p in [('limit', '\0\0\0\x02'), ('segv', '\0\x01\0\0')]:
76 > for n, p in [('limit', '\0\0\0\x02'), ('segv', '\0\x01\0\0')]:
75 > # corrupt p1 at rev0 and p2 at rev1
77 > # corrupt p1 at rev0 and p2 at rev1
76 > d = data[:24] + p + data[28:127 + 28] + p + data[127 + 32:]
78 > d = data[:24] + p + data[28:127 + 28] + p + data[127 + 32:]
77 > open(n + "/.hg/store/00changelog.i", "wb").write(d)
79 > open(n + "/.hg/store/00changelog.i", "wb").write(d)
78 > EOF
80 > EOF
79
81
80 $ hg debugindex -f1 limit/.hg/store/00changelog.i
82 $ hg debugindex -f1 limit/.hg/store/00changelog.i
81 rev flag offset length size base link p1 p2 nodeid
83 rev flag offset length size base link p1 p2 nodeid
82 0 0000 0 63 62 0 0 2 -1 7c31755bf9b5
84 0 0000 0 63 62 0 0 2 -1 7c31755bf9b5
83 1 0000 63 66 65 1 1 0 2 26333235a41c
85 1 0000 63 66 65 1 1 0 2 26333235a41c
84 $ hg debugindex -f1 segv/.hg/store/00changelog.i
86 $ hg debugindex -f1 segv/.hg/store/00changelog.i
85 rev flag offset length size base link p1 p2 nodeid
87 rev flag offset length size base link p1 p2 nodeid
86 0 0000 0 63 62 0 0 65536 -1 7c31755bf9b5
88 0 0000 0 63 62 0 0 65536 -1 7c31755bf9b5
87 1 0000 63 66 65 1 1 0 65536 26333235a41c
89 1 0000 63 66 65 1 1 0 65536 26333235a41c
88
90
89 $ cat <<EOF > test.py
91 $ cat <<EOF > test.py
90 > import sys
92 > import sys
91 > from mercurial import changelog, scmutil
93 > from mercurial import changelog, scmutil
92 > cl = changelog.changelog(scmutil.vfs(sys.argv[1]))
94 > cl = changelog.changelog(scmutil.vfs(sys.argv[1]))
93 > n0, n1 = cl.node(0), cl.node(1)
95 > n0, n1 = cl.node(0), cl.node(1)
94 > ops = [
96 > ops = [
95 > ('compute_phases_map_sets', lambda: cl.computephases([[0], []])),
97 > ('compute_phases_map_sets', lambda: cl.computephases([[0], []])),
96 > ('index_headrevs', lambda: cl.headrevs()),
98 > ('index_headrevs', lambda: cl.headrevs()),
97 > ('find_gca_candidates', lambda: cl.commonancestorsheads(n0, n1)),
99 > ('find_gca_candidates', lambda: cl.commonancestorsheads(n0, n1)),
98 > ('find_deepest', lambda: cl.ancestor(n0, n1)),
100 > ('find_deepest', lambda: cl.ancestor(n0, n1)),
99 > ]
101 > ]
100 > for l, f in ops:
102 > for l, f in ops:
101 > print l + ':',
103 > print l + ':',
102 > try:
104 > try:
103 > f()
105 > f()
104 > print 'uncaught buffer overflow?'
106 > print 'uncaught buffer overflow?'
105 > except ValueError, inst:
107 > except ValueError, inst:
106 > print inst
108 > print inst
107 > EOF
109 > EOF
108
110
109 $ python test.py limit/.hg/store
111 $ python test.py limit/.hg/store
110 compute_phases_map_sets: parent out of range
112 compute_phases_map_sets: parent out of range
111 index_headrevs: parent out of range
113 index_headrevs: parent out of range
112 find_gca_candidates: parent out of range
114 find_gca_candidates: parent out of range
113 find_deepest: parent out of range
115 find_deepest: parent out of range
114 $ python test.py segv/.hg/store
116 $ python test.py segv/.hg/store
115 compute_phases_map_sets: parent out of range
117 compute_phases_map_sets: parent out of range
116 index_headrevs: parent out of range
118 index_headrevs: parent out of range
117 find_gca_candidates: parent out of range
119 find_gca_candidates: parent out of range
118 find_deepest: parent out of range
120 find_deepest: parent out of range
119
121
120 $ cd ..
122 $ cd ..
123
124 #endif
General Comments 0
You need to be logged in to leave comments. Login now