changeset 26017:44705659da94

reachableroots: verify integer range of heads argument (issue4775) Now it raises IndexError instead of SEGV for 'wdir()' as it was before.
author Yuya Nishihara <yuya@tcha.org>
date Thu, 13 Aug 2015 18:38:46 +0900
parents c8d41c9c23c7
children c6115c30a376
files mercurial/parsers.c tests/test-parseindex.t
diffstat 2 files changed, 37 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/parsers.c	Thu Aug 13 18:29:38 2015 +0900
+++ b/mercurial/parsers.c	Thu Aug 13 18:38:46 2015 +0900
@@ -1167,6 +1167,10 @@
 	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;
--- a/tests/test-parseindex.t	Thu Aug 13 18:29:38 2015 +0900
+++ b/tests/test-parseindex.t	Thu Aug 13 18:38:46 2015 +0900
@@ -60,9 +60,40 @@
 
   $ cd ..
 
-Test corrupted p1/p2 fields that could cause SEGV at parsers.c:
+#if no-pure
+
+Test SEGV caused by bad revision passed to reachableroots() (issue4775):
+
+  $ cd a
 
-#if no-pure
+  $ 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:
 
   $ mkdir invalidparent
   $ cd invalidparent