reachableroots: bail if integer object cannot be allocated
This patch also replaces Py_XDECREF() by Py_DECREF() because we known "val"
and "p" are not NULL.
BTW, we can eliminate some of these allocation and error handling of int objects
if the internal "seen" array has more information. For example,
enum { SEEN = 1, ROOT = 2, REACHABLE = 4 };
/* ... build ROOT mask from roots argument ... */
if (seen[revnum + 1] & ROOT) { /* instead of PySet_Contains(roots, val) */
>From my quick hack, it is 2x faster.
--- a/mercurial/parsers.c Sat Aug 01 05:43:39 2015 -0700
+++ b/mercurial/parsers.c Fri Aug 14 12:31:56 2015 +0900
@@ -1185,14 +1185,16 @@
/* Add the node to reachable if it is a root*/
revnum = tovisit[k++];
val = PyInt_FromLong(revnum);
+ if (val == NULL)
+ goto bail;
if (PySet_Contains(roots, val) == 1) {
PySet_Add(reachable, val);
if (includepath == 0) {
- Py_XDECREF(val);
+ Py_DECREF(val);
continue;
}
}
- Py_XDECREF(val);
+ Py_DECREF(val);
/* Add its parents to the list of nodes to visit */
if (revnum != -1) {
@@ -1223,9 +1225,15 @@
goto bail;
for (k = 0; k < 2; k++) {
PyObject *p = PyInt_FromLong(parents[k]);
- if (PySet_Contains(reachable, p) == 1)
- PySet_Add(reachable, PyInt_FromLong(i));
- Py_XDECREF(p);
+ if (p == NULL)
+ goto bail;
+ if (PySet_Contains(reachable, p) == 1) {
+ val = PyInt_FromLong(i);
+ if (val == NULL)
+ goto bail;
+ PySet_Add(reachable, val);
+ }
+ Py_DECREF(p);
}
}
}