Patchwork [3,of,4] reachableroots: verify integer range of heads argument (issue4775)

login
register
mail settings
Submitter Yuya Nishihara
Date Aug. 13, 2015, 10:48 a.m.
Message ID <e650aa6ea4fb2866b545.1439462890@mimosa>
Download mbox | patch
Permalink /patch/10202/
State Accepted
Headers show

Comments

Yuya Nishihara - Aug. 13, 2015, 10:48 a.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1439458726 -32400
#      Thu Aug 13 18:38:46 2015 +0900
# Node ID e650aa6ea4fb2866b5457ea3ba361db81d6ccba8
# Parent  d03c861b206b28574ba277f58caa60a77d070f3e
reachableroots: verify integer range of heads argument (issue4775)

Now it raises IndexError instead of SEGV for 'wdir()' as it was before.

Patch

diff --git a/mercurial/parsers.c b/mercurial/parsers.c
--- a/mercurial/parsers.c
+++ b/mercurial/parsers.c
@@ -1167,6 +1167,10 @@  static PyObject *reachableroots(indexObj
 	numheads = PyList_GET_SIZE(heads);
 	for (i = 0; i < numheads; i++) {
 		revnum = PyInt_AS_LONG(PyList_GET_ITEM(heads, i));
+		if (revnum + 1 < 0 || revnum + 1 >= len + 1) {
+			PyErr_SetString(PyExc_IndexError, "head out of range");
+			goto bail;
+		}
 		if (seen[revnum+1] == 0) {
 			tovisit[lentovisit++] = revnum;
 			seen[revnum+1]=1;
diff --git a/tests/test-parseindex.t b/tests/test-parseindex.t
--- a/tests/test-parseindex.t
+++ b/tests/test-parseindex.t
@@ -60,10 +60,41 @@  We approximate that by reducing the read
 
   $ cd ..
 
+#if no-pure
+
+Test SEGV caused by bad revision passed to reachableroots() (issue4775):
+
+  $ cd a
+
+  $ python <<EOF
+  > from mercurial import changelog, scmutil
+  > cl = changelog.changelog(scmutil.vfs('.hg/store'))
+  > print 'goods:'
+  > for head in [0, len(cl) - 1, -1]:
+  >     print'%s: %r' % (head, cl.reachableroots(0, [head], set([0])))
+  > print 'bads:'
+  > for head in [len(cl), 10000, -2, -10000]:
+  >     print '%s:' % head,
+  >     try:
+  >         cl.reachableroots(0, [head], set([0]))
+  >         print 'uncaught buffer overflow?'
+  >     except IndexError as inst:
+  >         print inst
+  > EOF
+  goods:
+  0: <baseset [0]>
+  1: <baseset [0]>
+  -1: <baseset []>
+  bads:
+  2: head out of range
+  10000: head out of range
+  -2: head out of range
+  -10000: head out of range
+
+  $ cd ..
+
 Test corrupted p1/p2 fields that could cause SEGV at parsers.c:
 
-#if no-pure
-
   $ mkdir invalidparent
   $ cd invalidparent