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.
--- a/mercurial/parsers.c Thu Aug 13 18:38:46 2015 +0900
+++ b/mercurial/parsers.c Thu Aug 13 18:59:49 2015 +0900
@@ -1166,7 +1166,9 @@
/* 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;
--- a/tests/test-parseindex.t Thu Aug 13 18:38:46 2015 +0900
+++ b/tests/test-parseindex.t Thu Aug 13 18:59:49 2015 +0900
@@ -73,12 +73,12 @@
> 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 @@
10000: head out of range
-2: head out of range
-10000: head out of range
+ None: an integer is required
$ cd ..