##// END OF EJS Templates
test: clarify test-parseindex offsets...
marmoute -
r52071:a6c49e5d default
parent child Browse files
Show More
@@ -1,220 +1,225 b''
1 1 revlog.parseindex must be able to parse the index file even if
2 2 an index entry is split between two 64k blocks. The ideal test
3 3 would be to create an index file with inline data where
4 4 64k < size < 64k + 64 (64k is the size of the read buffer, 64 is
5 5 the size of an index entry) and with an index entry starting right
6 6 before the 64k block boundary, and try to read it.
7 7 We approximate that by reducing the read buffer to 1 byte.
8 8
9 9 $ hg init a
10 10 $ cd a
11 11 $ echo abc > foo
12 12 $ hg add foo
13 13 $ hg commit -m 'add foo'
14 14 $ echo >> foo
15 15 $ hg commit -m 'change foo'
16 16 $ hg log -r 0:
17 17 changeset: 0:7c31755bf9b5
18 18 user: test
19 19 date: Thu Jan 01 00:00:00 1970 +0000
20 20 summary: add foo
21 21
22 22 changeset: 1:26333235a41c
23 23 tag: tip
24 24 user: test
25 25 date: Thu Jan 01 00:00:00 1970 +0000
26 26 summary: change foo
27 27
28 28 $ cat >> test.py << EOF
29 29 > from mercurial import changelog, node, pycompat, vfs
30 30 >
31 31 > class singlebyteread(object):
32 32 > def __init__(self, real):
33 33 > self.real = real
34 34 >
35 35 > def read(self, size=-1):
36 36 > if size == 65536:
37 37 > size = 1
38 38 > return self.real.read(size)
39 39 >
40 40 > def __getattr__(self, key):
41 41 > return getattr(self.real, key)
42 42 >
43 43 > def __enter__(self):
44 44 > self.real.__enter__()
45 45 > return self
46 46 >
47 47 > def __exit__(self, *args, **kwargs):
48 48 > return self.real.__exit__(*args, **kwargs)
49 49 >
50 50 > def opener(*args):
51 51 > o = vfs.vfs(*args)
52 52 > def wrapper(*a, **kwargs):
53 53 > f = o(*a, **kwargs)
54 54 > return singlebyteread(f)
55 55 > wrapper.options = o.options
56 56 > return wrapper
57 57 >
58 58 > cl = changelog.changelog(opener(b'.hg/store'))
59 59 > print(len(cl), 'revisions:')
60 60 > for r in cl:
61 61 > print(pycompat.sysstr(node.short(cl.node(r))))
62 62 > EOF
63 63 $ "$PYTHON" test.py
64 64 2 revisions:
65 65 7c31755bf9b5
66 66 26333235a41c
67 67
68 68 $ cd ..
69 69
70 70 #if no-pure
71 71
72 72 Test SEGV caused by bad revision passed to reachableroots() (issue4775):
73 73
74 74 $ cd a
75 75
76 76 $ "$PYTHON" <<EOF
77 77 > from mercurial import changelog, vfs
78 78 > cl = changelog.changelog(vfs.vfs(b'.hg/store'))
79 79 > print('good heads:')
80 80 > for head in [0, len(cl) - 1, -1]:
81 81 > print('%s: %r' % (head, cl.reachableroots(0, [head], [0])))
82 82 > print('bad heads:')
83 83 > for head in [len(cl), 10000, -2, -10000, None]:
84 84 > print('%s:' % head, end=' ')
85 85 > try:
86 86 > cl.reachableroots(0, [head], [0])
87 87 > print('uncaught buffer overflow?')
88 88 > except (IndexError, TypeError) as inst:
89 89 > print(inst)
90 90 > print('good roots:')
91 91 > for root in [0, len(cl) - 1, -1]:
92 92 > print('%s: %r' % (root, cl.reachableroots(root, [len(cl) - 1], [root])))
93 93 > print('out-of-range roots are ignored:')
94 94 > for root in [len(cl), 10000, -2, -10000]:
95 95 > print('%s: %r' % (root, cl.reachableroots(root, [len(cl) - 1], [root])))
96 96 > print('bad roots:')
97 97 > for root in [None]:
98 98 > print('%s:' % root, end=' ')
99 99 > try:
100 100 > cl.reachableroots(root, [len(cl) - 1], [root])
101 101 > print('uncaught error?')
102 102 > except TypeError as inst:
103 103 > print(inst)
104 104 > EOF
105 105 good heads:
106 106 0: [0]
107 107 1: [0]
108 108 -1: []
109 109 bad heads:
110 110 2: head out of range
111 111 10000: head out of range
112 112 -2: head out of range
113 113 -10000: head out of range
114 114 None: (an integer is required( .got type NoneType.)?|'NoneType' object cannot be interpreted as an integer) (re)
115 115 good roots:
116 116 0: [0]
117 117 1: [1]
118 118 -1: [-1]
119 119 out-of-range roots are ignored:
120 120 2: []
121 121 10000: []
122 122 -2: []
123 123 -10000: []
124 124 bad roots:
125 125 None: (an integer is required( .got type NoneType.)?|'NoneType' object cannot be interpreted as an integer) (re)
126 126
127 127 $ cd ..
128 128
129 129 Test corrupted p1/p2 fields that could cause SEGV at parsers.c:
130 130
131 131 $ mkdir invalidparent
132 132 $ cd invalidparent
133 133
134 134 $ hg clone --pull -q --config phases.publish=False ../a limit --config format.sparse-revlog=no
135 135 $ hg clone --pull -q --config phases.publish=False ../a neglimit --config format.sparse-revlog=no
136 136 $ hg clone --pull -q --config phases.publish=False ../a segv --config format.sparse-revlog=no
137 137 $ rm -R limit/.hg/cache neglimit/.hg/cache segv/.hg/cache
138 138
139 139 $ "$PYTHON" <<EOF
140 140 > data = open("limit/.hg/store/00changelog.i", "rb").read()
141 141 > poisons = [
142 142 > (b'limit', b'\0\0\0\x02'),
143 143 > (b'neglimit', b'\xff\xff\xff\xfe'),
144 144 > (b'segv', b'\0\x01\0\0'),
145 145 > ]
146 146 > for n, p in poisons:
147 147 > # corrupt p1 at rev0 and p2 at rev1
148 > d = data[:24] + p + data[28:127 + 28] + p + data[127 + 32:]
149 > open(n + b"/.hg/store/00changelog.i", "wb").write(d)
148 > rev_0 = data[:64 + 63]
149 > rev_1 = data[64 + 63:]
150 > altered_rev_0 = rev_0[:24] + p + rev_0[24 + 4:]
151 > altered_rev_1 = rev_1[:28] + p + rev_1[28 + 4:]
152 > new_data = altered_rev_0 + altered_rev_1
153 > with open(n + b"/.hg/store/00changelog.i", "wb") as f:
154 > f.write(new_data)
150 155 > EOF
151 156
152 157 $ hg -R limit debugrevlogindex -f1 -c
153 158 rev flag size link p1 p2 nodeid
154 159 0 0000 62 0 2 -1 7c31755bf9b5
155 160 1 0000 65 1 0 2 26333235a41c
156 161
157 162 $ hg -R limit debugdeltachain -c
158 163 rev p1 p2 chain# chainlen prev delta
159 164 0 2 -1 1 1 -1 base
160 165 1 0 2 2 1 -1 base
161 166
162 167 $ hg -R neglimit debugrevlogindex -f1 -c
163 168 rev flag size link p1 p2 nodeid
164 169 0 0000 62 0 -2 -1 7c31755bf9b5
165 170 1 0000 65 1 0 -2 26333235a41c
166 171
167 172 $ hg -R segv debugrevlogindex -f1 -c
168 173 rev flag size link p1 p2 nodeid
169 174 0 0000 62 0 65536 -1 7c31755bf9b5
170 175 1 0000 65 1 0 65536 26333235a41c
171 176
172 177 $ hg -R segv debugdeltachain -c
173 178 rev p1 p2 chain# chainlen prev delta
174 179 0 65536 -1 1 1 -1 base
175 180 1 0 65536 2 1 -1 base
176 181
177 182 $ cat <<EOF > test.py
178 183 > import sys
179 184 > from mercurial import changelog, pycompat, vfs
180 185 > cl = changelog.changelog(vfs.vfs(pycompat.fsencode(sys.argv[1])))
181 186 > n0, n1 = cl.node(0), cl.node(1)
182 187 > ops = [
183 188 > ('reachableroots',
184 189 > lambda: cl.index.reachableroots2(0, [1], [0], False)),
185 190 > ('compute_phases_map_sets', lambda: cl.computephases({1: {cl.node(0)}})),
186 191 > ('index_headrevs', lambda: cl.headrevs()),
187 192 > ('find_gca_candidates', lambda: cl.commonancestorsheads(n0, n1)),
188 193 > ('find_deepest', lambda: cl.ancestor(n0, n1)),
189 194 > ]
190 195 > for l, f in ops:
191 196 > print(l + ':', end=' ')
192 197 > try:
193 198 > f()
194 199 > print('uncaught buffer overflow?')
195 200 > except ValueError as inst:
196 201 > print(inst)
197 202 > EOF
198 203
199 204 $ "$PYTHON" test.py limit/.hg/store
200 205 reachableroots: parent out of range
201 206 compute_phases_map_sets: parent out of range
202 207 index_headrevs: parent out of range
203 208 find_gca_candidates: parent out of range
204 209 find_deepest: parent out of range
205 210 $ "$PYTHON" test.py neglimit/.hg/store
206 211 reachableroots: parent out of range
207 212 compute_phases_map_sets: parent out of range
208 213 index_headrevs: parent out of range
209 214 find_gca_candidates: parent out of range
210 215 find_deepest: parent out of range
211 216 $ "$PYTHON" test.py segv/.hg/store
212 217 reachableroots: parent out of range
213 218 compute_phases_map_sets: parent out of range
214 219 index_headrevs: parent out of range
215 220 find_gca_candidates: parent out of range
216 221 find_deepest: parent out of range
217 222
218 223 $ cd ..
219 224
220 225 #endif
General Comments 0
You need to be logged in to leave comments. Login now