--- a/tests/test-parseindex.t Thu Jul 16 11:12:15 2015 -0700
+++ b/tests/test-parseindex.t Thu Jul 16 23:36:08 2015 +0900
@@ -59,3 +59,62 @@
26333235a41c
$ cd ..
+
+Test corrupted p1/p2 fields that could cause SEGV at parsers.c:
+
+ $ 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
+
+ $ python <<EOF
+ > data = open("limit/.hg/store/00changelog.i", "rb").read()
+ > for n, p in [('limit', '\0\0\0\x02'), ('segv', '\0\x01\0\0')]:
+ > # corrupt p1 at rev0 and p2 at rev1
+ > d = data[:24] + p + data[28:127 + 28] + p + data[127 + 32:]
+ > open(n + "/.hg/store/00changelog.i", "wb").write(d)
+ > EOF
+
+ $ hg debugindex -f1 limit/.hg/store/00changelog.i
+ rev flag offset length size base link p1 p2 nodeid
+ 0 0000 0 63 62 0 0 2 -1 7c31755bf9b5
+ 1 0000 63 66 65 1 1 0 2 26333235a41c
+ $ hg debugindex -f1 segv/.hg/store/00changelog.i
+ rev flag offset length size base link p1 p2 nodeid
+ 0 0000 0 63 62 0 0 65536 -1 7c31755bf9b5
+ 1 0000 63 66 65 1 1 0 65536 26333235a41c
+
+ $ cat <<EOF > test.py
+ > import sys
+ > from mercurial import changelog, scmutil
+ > cl = changelog.changelog(scmutil.vfs(sys.argv[1]))
+ > n0, n1 = cl.node(0), cl.node(1)
+ > ops = [
+ > ('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:
+ > print l + ':',
+ > try:
+ > f()
+ > print 'uncaught buffer overflow?'
+ > except ValueError, inst:
+ > print inst
+ > EOF
+
+ $ python test.py limit/.hg/store
+ 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
+ $ python test.py segv/.hg/store
+ 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 ..