Patchwork D5235: revlog: replace PyInt_AS_LONG with a more portable helper function

login
register
mail settings
Submitter phabricator
Date Nov. 13, 2018, 11:42 a.m.
Message ID <d79d0b5d6d1bc4a41d916a2b87e0fdce@localhost.localdomain>
Download mbox | patch
Permalink /patch/36535/
State Not Applicable
Headers show

Comments

phabricator - Nov. 13, 2018, 11:42 a.m.
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGfa33196088c4: revlog: replace PyInt_AS_LONG with a more portable helper function (authored by durin42, committed by ).

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D5235?vs=12502&id=12509#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5235?vs=12502&id=12509

REVISION DETAIL
  https://phab.mercurial-scm.org/D5235

AFFECTED FILES
  mercurial/cext/revlog.c
  mercurial/cext/util.h

CHANGE DETAILS




To: durin42, #hg-reviewers
Cc: yuja, mercurial-devel

Patch

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 @@ 
 	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_ */
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 @@ 
                                     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 @@ 
 		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 @@ 
 	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 @@ 
 	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 @@ 
 	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 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 = {