revlog: catch revlog corruption in index_baserev
A revision cannot use a base above itself, it can only happens one corrupted
repository.
Ignoring such corrupted could lead to infinite loop.
--- a/mercurial/cext/revlog.c Fri Dec 21 17:36:12 2018 -0500
+++ b/mercurial/cext/revlog.c Thu Dec 27 23:34:37 2018 +0100
@@ -842,10 +842,11 @@
static inline int index_baserev(indexObject *self, int rev)
{
const char *data;
+ int result;
if (rev >= self->length) {
PyObject *tuple = PyList_GET_ITEM(self->added, rev - self->length);
- return (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 3));
+ result = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 3));
}
else {
data = index_deref(self, rev);
@@ -853,8 +854,16 @@
return -2;
}
- return getbe32(data + 16);
+ result = getbe32(data + 16);
}
+ if (result > rev) {
+ PyErr_Format(
+ PyExc_ValueError,
+ "corrupted revlog, revision base above revision: %d, %d",
+ rev, result);
+ return -2;
+ }
+ return result;
}
static PyObject *index_deltachain(indexObject *self, PyObject *args)