Mercurial > hg
comparison tests/test-parseindex.t @ 25810:82d6a35cf432
parsers: fix buffer overflow by invalid parent revision read from revlog
If revlog file is corrupted, it can have parent pointing to invalid revision.
So we should validate it before updating nothead[], phases[], seen[], etc.
Otherwise it would cause segfault at best.
We could use "rev" instead of "maxrev" as upper bound, but I think the explicit
"maxrev" can clarify that we just want to avoid possible buffer overflow
vulnerability.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Thu, 16 Jul 2015 23:36:08 +0900 |
parents | f2719b387380 |
children | 1619563959b3 |
comparison
equal
deleted
inserted
replaced
25809:ebb5bb9bc32e | 25810:82d6a35cf432 |
---|---|
57 2 revisions: | 57 2 revisions: |
58 7c31755bf9b5 | 58 7c31755bf9b5 |
59 26333235a41c | 59 26333235a41c |
60 | 60 |
61 $ cd .. | 61 $ cd .. |
62 | |
63 Test corrupted p1/p2 fields that could cause SEGV at parsers.c: | |
64 | |
65 $ mkdir invalidparent | |
66 $ cd invalidparent | |
67 | |
68 $ hg clone --pull -q --config phases.publish=False ../a limit | |
69 $ hg clone --pull -q --config phases.publish=False ../a segv | |
70 $ rm -R limit/.hg/cache segv/.hg/cache | |
71 | |
72 $ python <<EOF | |
73 > data = open("limit/.hg/store/00changelog.i", "rb").read() | |
74 > for n, p in [('limit', '\0\0\0\x02'), ('segv', '\0\x01\0\0')]: | |
75 > # corrupt p1 at rev0 and p2 at rev1 | |
76 > d = data[:24] + p + data[28:127 + 28] + p + data[127 + 32:] | |
77 > open(n + "/.hg/store/00changelog.i", "wb").write(d) | |
78 > EOF | |
79 | |
80 $ hg debugindex -f1 limit/.hg/store/00changelog.i | |
81 rev flag offset length size base link p1 p2 nodeid | |
82 0 0000 0 63 62 0 0 2 -1 7c31755bf9b5 | |
83 1 0000 63 66 65 1 1 0 2 26333235a41c | |
84 $ hg debugindex -f1 segv/.hg/store/00changelog.i | |
85 rev flag offset length size base link p1 p2 nodeid | |
86 0 0000 0 63 62 0 0 65536 -1 7c31755bf9b5 | |
87 1 0000 63 66 65 1 1 0 65536 26333235a41c | |
88 | |
89 $ cat <<EOF > test.py | |
90 > import sys | |
91 > from mercurial import changelog, scmutil | |
92 > cl = changelog.changelog(scmutil.vfs(sys.argv[1])) | |
93 > n0, n1 = cl.node(0), cl.node(1) | |
94 > ops = [ | |
95 > ('compute_phases_map_sets', lambda: cl.computephases([[0], []])), | |
96 > ('index_headrevs', lambda: cl.headrevs()), | |
97 > ('find_gca_candidates', lambda: cl.commonancestorsheads(n0, n1)), | |
98 > ('find_deepest', lambda: cl.ancestor(n0, n1)), | |
99 > ] | |
100 > for l, f in ops: | |
101 > print l + ':', | |
102 > try: | |
103 > f() | |
104 > print 'uncaught buffer overflow?' | |
105 > except ValueError, inst: | |
106 > print inst | |
107 > EOF | |
108 | |
109 $ python test.py limit/.hg/store | |
110 compute_phases_map_sets: parent out of range | |
111 index_headrevs: parent out of range | |
112 find_gca_candidates: parent out of range | |
113 find_deepest: parent out of range | |
114 $ python test.py segv/.hg/store | |
115 compute_phases_map_sets: parent out of range | |
116 index_headrevs: parent out of range | |
117 find_gca_candidates: parent out of range | |
118 find_deepest: parent out of range | |
119 | |
120 $ cd .. |