# HG changeset patch # User Boris Feld # Date 2018-12-27 22:34:37 # Node ID f4113489e4d493ffb0aa6c3c58454dc7e3b82e83 # Parent d7d3164e6a31193e8fa2fb9042183ce2487edb49 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. diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c --- a/mercurial/cext/revlog.c +++ b/mercurial/cext/revlog.c @@ -842,10 +842,11 @@ bail: 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 @@ static inline int index_baserev(indexObj 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)