# HG changeset patch # User Augie Fackler # Date 2018-11-06 16:12:56 # Node ID fa33196088c454ca9154e708c4b4976b139921b4 # Parent 04d08f17ce7a2049476ccf9095af83322fea31a3 revlog: replace PyInt_AS_LONG with a more portable helper function PyInt_AS_LONG disappears on Python, and our previous #define was producing some problems on Python 3. Let's give up and make an inline helper function that makes this more sane. Differential Revision: https://phab.mercurial-scm.org/D5235 diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c --- a/mercurial/cext/revlog.c +++ b/mercurial/cext/revlog.c @@ -24,7 +24,6 @@ #define PyInt_Check PyLong_Check #define PyInt_FromLong PyLong_FromLong #define PyInt_FromSsize_t PyLong_FromSsize_t -#define PyInt_AS_LONG PyLong_AS_LONG #define PyInt_AsLong PyLong_AsLong #endif @@ -161,10 +160,17 @@ static inline int index_get_parents(inde int maxrev) { if (rev >= self->length) { + long tmp; PyObject *tuple = PyList_GET_ITEM(self->added, rev - self->length); - ps[0] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 5)); - ps[1] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 6)); + if (!pylong_to_long(PyTuple_GET_ITEM(tuple, 5), &tmp)) { + return -1; + } + ps[0] = (int)tmp; + if (!pylong_to_long(PyTuple_GET_ITEM(tuple, 6), &tmp)) { + return -1; + } + ps[1] = (int)tmp; } else { const char *data = index_deref(self, rev); ps[0] = getbe32(data + 24); @@ -464,7 +470,10 @@ static Py_ssize_t add_roots_get_min(inde if (iter == NULL) return -2; while ((iter_item = PyIter_Next(iter))) { - iter_item_long = PyInt_AS_LONG(iter_item); + if (!pylong_to_long(iter_item, &iter_item_long)) { + Py_DECREF(iter_item); + return -2; + } Py_DECREF(iter_item); if (iter_item_long < min_idx) min_idx = iter_item_long; @@ -853,7 +862,11 @@ static inline int index_baserev(indexObj if (rev >= self->length) { PyObject *tuple = PyList_GET_ITEM(self->added, rev - self->length); - return (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 3)); + long ret; + if (!pylong_to_long(PyTuple_GET_ITEM(tuple, 3), &ret)) { + return -2; + } + return (int)ret; } else { data = index_deref(self, rev); if (data == NULL) { @@ -1384,8 +1397,13 @@ static PyObject *index_getitem(indexObje char *node; int rev; - if (PyInt_Check(value)) - return index_get(self, PyInt_AS_LONG(value)); + if (PyInt_Check(value)) { + long idx; + if (!pylong_to_long(value, &idx)) { + return NULL; + } + return index_get(self, idx); + } if (node_check(value, &node) == -1) return NULL; @@ -1516,7 +1534,10 @@ static int index_contains(indexObject *s char *node; if (PyInt_Check(value)) { - long rev = PyInt_AS_LONG(value); + long rev; + if (!pylong_to_long(value, &rev)) { + return -1; + } return rev >= -1 && rev < index_length(self); } @@ -2404,10 +2425,12 @@ static PyObject *rustla_next(rustlazyanc static int rustla_contains(rustlazyancestorsObject *self, PyObject *rev) { - if (!(PyInt_Check(rev))) { + long lrev; + if (!pylong_to_long(rev, &lrev)) { + PyErr_Clear(); return 0; } - return rustlazyancestors_contains(self->iter, PyInt_AS_LONG(rev)); + return rustlazyancestors_contains(self->iter, lrev); } static PySequenceMethods rustla_sequence_methods = { diff --git a/mercurial/cext/util.h b/mercurial/cext/util.h --- a/mercurial/cext/util.h +++ b/mercurial/cext/util.h @@ -58,4 +58,17 @@ static inline PyObject *_dict_new_presiz return _PyDict_NewPresized(((1 + expected_size) / 2) * 3); } +/* Convert a PyInt or PyLong to a long. Returns false if there is an + error, in which case an exception will already have been set. */ +static inline bool pylong_to_long(PyObject *pylong, long *out) +{ + *out = PyLong_AsLong(pylong); + /* Fast path to avoid hitting PyErr_Occurred if the value was obviously + * not an error. */ + if (*out != -1) { + return true; + } + return PyErr_Occurred() == NULL; +} + #endif /* _HG_UTIL_H_ */