test-parseindex.t
206 lines
| 6.4 KiB
| text/troff
|
Tads3Lexer
/ tests / test-parseindex.t
|
r12476 | revlog.parseindex must be able to parse the index file even if | ||
an index entry is split between two 64k blocks. The ideal test | ||||
would be to create an index file with inline data where | ||||
64k < size < 64k + 64 (64k is the size of the read buffer, 64 is | ||||
the size of an index entry) and with an index entry starting right | ||||
before the 64k block boundary, and try to read it. | ||||
We approximate that by reducing the read buffer to 1 byte. | ||||
$ hg init a | ||||
$ cd a | ||||
$ echo abc > foo | ||||
$ hg add foo | ||||
$ hg commit -m 'add foo' | ||||
$ echo >> foo | ||||
$ hg commit -m 'change foo' | ||||
$ hg log -r 0: | ||||
changeset: 0:7c31755bf9b5 | ||||
user: test | ||||
date: Thu Jan 01 00:00:00 1970 +0000 | ||||
summary: add foo | ||||
changeset: 1:26333235a41c | ||||
tag: tip | ||||
user: test | ||||
date: Thu Jan 01 00:00:00 1970 +0000 | ||||
summary: change foo | ||||
$ cat >> test.py << EOF | ||||
|
r38090 | > from __future__ import print_function | ||
|
r31250 | > from mercurial import changelog, vfs | ||
|
r12476 | > from mercurial.node import * | ||
> | ||||
> class singlebyteread(object): | ||||
> def __init__(self, real): | ||||
> self.real = real | ||||
> | ||||
> def read(self, size=-1): | ||||
> if size == 65536: | ||||
> size = 1 | ||||
> return self.real.read(size) | ||||
> | ||||
> def __getattr__(self, key): | ||||
> return getattr(self.real, key) | ||||
> | ||||
|
r35984 | > def __enter__(self): | ||
> self.real.__enter__() | ||||
> return self | ||||
> | ||||
> def __exit__(self, *args, **kwargs): | ||||
> return self.real.__exit__(*args, **kwargs) | ||||
> | ||||
|
r12476 | > def opener(*args): | ||
|
r31250 | > o = vfs.vfs(*args) | ||
|
r35983 | > def wrapper(*a, **kwargs): | ||
> f = o(*a, **kwargs) | ||||
|
r12476 | > return singlebyteread(f) | ||
> return wrapper | ||||
> | ||||
> cl = changelog.changelog(opener('.hg/store')) | ||||
|
r38090 | > print(len(cl), 'revisions:') | ||
|
r12476 | > for r in cl: | ||
|
r38090 | > print(short(cl.node(r))) | ||
|
r12476 | > EOF | ||
|
r32940 | $ $PYTHON test.py | ||
|
r12476 | 2 revisions: | ||
7c31755bf9b5 | ||||
26333235a41c | ||||
|
r16913 | |||
$ cd .. | ||||
|
r25810 | |||
|
r26017 | #if no-pure | ||
Test SEGV caused by bad revision passed to reachableroots() (issue4775): | ||||
$ cd a | ||||
|
r25810 | |||
|
r33262 | $ $PYTHON <<EOF | ||
|
r38090 | > from __future__ import print_function | ||
|
r31250 | > from mercurial import changelog, vfs | ||
> cl = changelog.changelog(vfs.vfs('.hg/store')) | ||||
|
r38090 | > print('good heads:') | ||
|
r26017 | > for head in [0, len(cl) - 1, -1]: | ||
|
r38090 | > print('%s: %r' % (head, cl.reachableroots(0, [head], [0]))) | ||
> print('bad heads:') | ||||
|
r26018 | > for head in [len(cl), 10000, -2, -10000, None]: | ||
|
r38090 | > print('%s:' % head, end=' ') | ||
|
r26017 | > try: | ||
|
r26053 | > cl.reachableroots(0, [head], [0]) | ||
|
r38090 | > print('uncaught buffer overflow?') | ||
|
r26018 | > except (IndexError, TypeError) as inst: | ||
|
r38090 | > print(inst) | ||
> print('good roots:') | ||||
|
r26053 | > for root in [0, len(cl) - 1, -1]: | ||
|
r38090 | > print('%s: %r' % (root, cl.reachableroots(root, [len(cl) - 1], [root]))) | ||
> print('out-of-range roots are ignored:') | ||||
|
r26053 | > for root in [len(cl), 10000, -2, -10000]: | ||
|
r38090 | > print('%s: %r' % (root, cl.reachableroots(root, [len(cl) - 1], [root]))) | ||
> print('bad roots:') | ||||
|
r26053 | > for root in [None]: | ||
|
r38090 | > print('%s:' % root, end=' ') | ||
|
r26053 | > try: | ||
> cl.reachableroots(root, [len(cl) - 1], [root]) | ||||
|
r38090 | > print('uncaught error?') | ||
|
r26053 | > except TypeError as inst: | ||
|
r38090 | > print(inst) | ||
|
r26017 | > EOF | ||
|
r26053 | good heads: | ||
|
r26094 | 0: [0] | ||
1: [0] | ||||
-1: [] | ||||
|
r26053 | bad heads: | ||
|
r26017 | 2: head out of range | ||
10000: head out of range | ||||
-2: head out of range | ||||
-10000: head out of range | ||||
|
r26018 | None: an integer is required | ||
|
r26053 | good roots: | ||
|
r26094 | 0: [0] | ||
1: [1] | ||||
-1: [-1] | ||||
|
r26053 | out-of-range roots are ignored: | ||
|
r26094 | 2: [] | ||
10000: [] | ||||
-2: [] | ||||
-10000: [] | ||||
|
r26053 | bad roots: | ||
None: an integer is required | ||||
|
r26017 | |||
$ cd .. | ||||
Test corrupted p1/p2 fields that could cause SEGV at parsers.c: | ||||
|
r25859 | |||
|
r25810 | $ mkdir invalidparent | ||
$ cd invalidparent | ||||
$ hg clone --pull -q --config phases.publish=False ../a limit | ||||
$ hg clone --pull -q --config phases.publish=False ../a segv | ||||
$ rm -R limit/.hg/cache segv/.hg/cache | ||||
|
r33262 | $ $PYTHON <<EOF | ||
|
r25810 | > data = open("limit/.hg/store/00changelog.i", "rb").read() | ||
|
r38098 | > for n, p in [(b'limit', b'\0\0\0\x02'), (b'segv', b'\0\x01\0\0')]: | ||
|
r25810 | > # corrupt p1 at rev0 and p2 at rev1 | ||
> d = data[:24] + p + data[28:127 + 28] + p + data[127 + 32:] | ||||
|
r38098 | > open(n + b"/.hg/store/00changelog.i", "wb").write(d) | ||
|
r25810 | > EOF | ||
|
r37298 | $ hg -R limit debugindex -f1 -c | ||
|
r37301 | rev flag size link p1 p2 nodeid | ||
0 0000 62 0 2 -1 7c31755bf9b5 | ||||
1 0000 65 1 0 2 26333235a41c | ||||
|
r37299 | |||
$ hg -R limit debugdeltachain -c | ||||
rev chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio | ||||
0 1 1 -1 base 63 62 63 1.01613 63 0 0.00000 | ||||
1 2 1 -1 base 66 65 66 1.01538 66 0 0.00000 | ||||
|
r37298 | $ hg -R segv debugindex -f1 -c | ||
|
r37301 | rev flag size link p1 p2 nodeid | ||
0 0000 62 0 65536 -1 7c31755bf9b5 | ||||
1 0000 65 1 0 65536 26333235a41c | ||||
|
r25810 | |||
|
r37299 | $ hg -R segv debugdeltachain -c | ||
rev chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio | ||||
0 1 1 -1 base 63 62 63 1.01613 63 0 0.00000 | ||||
1 2 1 -1 base 66 65 66 1.01538 66 0 0.00000 | ||||
|
r25810 | $ cat <<EOF > test.py | ||
|
r38090 | > from __future__ import print_function | ||
|
r25810 | > import sys | ||
|
r31250 | > from mercurial import changelog, vfs | ||
> cl = changelog.changelog(vfs.vfs(sys.argv[1])) | ||||
|
r25810 | > n0, n1 = cl.node(0), cl.node(1) | ||
> ops = [ | ||||
|
r26016 | > ('reachableroots', | ||
|
r26053 | > lambda: cl.index.reachableroots2(0, [1], [0], False)), | ||
|
r25810 | > ('compute_phases_map_sets', lambda: cl.computephases([[0], []])), | ||
> ('index_headrevs', lambda: cl.headrevs()), | ||||
> ('find_gca_candidates', lambda: cl.commonancestorsheads(n0, n1)), | ||||
> ('find_deepest', lambda: cl.ancestor(n0, n1)), | ||||
> ] | ||||
> for l, f in ops: | ||||
|
r38090 | > print(l + ':', end=' ') | ||
|
r25810 | > try: | ||
> f() | ||||
|
r38090 | > print('uncaught buffer overflow?') | ||
|
r38100 | > except ValueError as inst: | ||
|
r38090 | > print(inst) | ||
|
r25810 | > EOF | ||
|
r32940 | $ $PYTHON test.py limit/.hg/store | ||
|
r26016 | reachableroots: parent out of range | ||
|
r25810 | compute_phases_map_sets: parent out of range | ||
index_headrevs: parent out of range | ||||
find_gca_candidates: parent out of range | ||||
find_deepest: parent out of range | ||||
|
r32940 | $ $PYTHON test.py segv/.hg/store | ||
|
r26016 | reachableroots: parent out of range | ||
|
r25810 | compute_phases_map_sets: parent out of range | ||
index_headrevs: parent out of range | ||||
find_gca_candidates: parent out of range | ||||
find_deepest: parent out of range | ||||
$ cd .. | ||||
|
r25859 | |||
#endif | ||||