Patchwork [4,of,4] reachableroots: verify type of each item of heads argument

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

Comments

Yuya Nishihara - Aug. 13, 2015, 10:48 a.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1439459989 -32400
#      Thu Aug 13 18:59:49 2015 +0900
# Node ID 3e005964350afc0a39ce7fbade9409cb3ba1653f
# Parent  e650aa6ea4fb2866b5457ea3ba361db81d6ccba8
reachableroots: verify type of each item of heads argument

Though PyInt_AS_LONG() can return a value no matter if it isn't an int object,
it could exceed the boundary of the underlying struct. I think C API should be
defensive to such errors.
Matt Mackall - Aug. 13, 2015, 10:12 p.m.
On Thu, 2015-08-13 at 19:48 +0900, Yuya Nishihara wrote:
> # HG changeset patch
> # User Yuya Nishihara <yuya@tcha.org>
> # Date 1439459989 -32400
> #      Thu Aug 13 18:59:49 2015 +0900
> # Node ID 3e005964350afc0a39ce7fbade9409cb3ba1653f
> # Parent  e650aa6ea4fb2866b5457ea3ba361db81d6ccba8
> reachableroots: verify type of each item of heads argument

These are queued for default, thanks.

Patch

diff --git a/mercurial/parsers.c b/mercurial/parsers.c
--- a/mercurial/parsers.c
+++ b/mercurial/parsers.c
@@ -1166,7 +1166,9 @@  static PyObject *reachableroots(indexObj
 	/* Populate tovisit with all the heads */
 	numheads = PyList_GET_SIZE(heads);
 	for (i = 0; i < numheads; i++) {
-		revnum = PyInt_AS_LONG(PyList_GET_ITEM(heads, i));
+		revnum = PyInt_AsLong(PyList_GET_ITEM(heads, i));
+		if (revnum == -1 && PyErr_Occurred())
+			goto bail;
 		if (revnum + 1 < 0 || revnum + 1 >= len + 1) {
 			PyErr_SetString(PyExc_IndexError, "head out of range");
 			goto bail;
diff --git a/tests/test-parseindex.t b/tests/test-parseindex.t
--- a/tests/test-parseindex.t
+++ b/tests/test-parseindex.t
@@ -73,12 +73,12 @@  Test SEGV caused by bad revision passed 
   > 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]:
+  > for head in [len(cl), 10000, -2, -10000, None]:
   >     print '%s:' % head,
   >     try:
   >         cl.reachableroots(0, [head], set([0]))
   >         print 'uncaught buffer overflow?'
-  >     except IndexError as inst:
+  >     except (IndexError, TypeError) as inst:
   >         print inst
   > EOF
   goods:
@@ -90,6 +90,7 @@  Test SEGV caused by bad revision passed 
   10000: head out of range
   -2: head out of range
   -10000: head out of range
+  None: an integer is required
 
   $ cd ..